Ler dados para um array de string na linguagem C

Boa Tarde,

   Gostaria de saber como posso ler dados em uma matrix de strings, gostaria de ler caracter por caracter, tentei dessa maneira.


int main(void)
{
	int i,j;
	char field[10000][10000],c;

	while((c = getchar())){

		if(c == 0)
			break;

		for (i = 0; i < 10; ++i){
			for (j = 0; j < 5; ++j)
				field[i][j] = c;
		}

		printf("%c\n",field[0][1]);

	}

	return 0;

No meu ver o que vem da variavel C entraria na linha i e coluna j alimentando assim coluna após coluna e após isso as linhas, ai faço um teste para pegar um caracter de um determinado ponto, printf("%c\n",field[0][1]);. Bom o ponto é o seguinte o programa até compila mas depois da falha de segmentação, eu fui atrás e isso diz que eu estou tentando acessar um ponto no array que não há nada. Alguém teria alguma sugestão de como eu poderia fazer essa leitura? Obrigado.

Olá,

O erro segmentation fault está dando porque você está declarando uma variável muito grande para o stack (field[10000][10000] ).
(O segmentation fault normalmente acontece na situação que você mencionou, acessar um endereço que não existe, mas nesse caso a mensagem está um pouco mal colocada mesmo… o que aconteceu foi um stack overflow)

Soluções:

diminuir essa variável caso não precise de tanto assim (tirei um zero aqui e funcionou: field[1000][1000] )
ou
declare essa variável no heap, caso realmente ela tenha que ter esse tamanhão: #include <stdlib.h> // .... char * field = malloc(sizeof(char)*10000*10000); // E no final do programa... free(field);

Mais uma coisa:
Eu coloquei a dica sobre o erro de memória, mas o programa ainda tem erros de lógica e provavelmente não vai fazer o que você espera. Vou deixar para você fuçar mais um pouco e descobrir.

Poisé só que eu tenho que colocar esses valores por que são os valores maximos que o enunciado do problema me deu entende, não teria outra maneira de fazer isso?

O limite do tamanho do stack é fixo por plataforma (ou melhor, aqui diz que no Windows dá para configurar no compilador, caso queira testar: http://www.cs.nyu.edu/exact/core/doc/stackOverflow.txt).

Mas se você alocar o array usando malloc (ver na resposta anterior) não tem esse limite, pode alocar quanto quiser dentro da quantidade disponível na máquina. Para usar o array alocado dinamicamente é igualzinho. Ex:

char * field = malloc(sizeof(char)*10000*10000); // Solicita uma área de 10000 * 10000

field[0][1] = 'A'; // Usa como se fosse um array estático.

free(field); // Devolve a memória após o uso.

Se esse tamanho é realmente o que precisa é só fazer assim, não muda nada a não ser a declaração e o free no final.

De modo geral, é recomendável:
a) Não ler caracter por caracter e sim linha por linha - é muito mais rápido
b) Não criar arrays bidimensionais gigantes, que só ocupam espaço à toa. Em vez disso, aloque só a memória necessária.

Digamos que seu arquivo tenha no máximo 10000 linhas (um arquivinho pequeno, por sinal), e cada linha tenha no máximo 1000 caracteres. O que você faria:

#include <stdio.h>
#include <stdlib.h> 
#include <string.h> /* strdup */

#define MAXLINHAS 10000
#define MAXTAMLINHA 1000

int main (int argc, char *argv[]) {
    char linha [MAXTAMLINHA+1];
    char *linhasDoArquivo[MAXLINHAS];
    FILE *arquivo;
    int nLinha;
    int i;

    /* Checando se ha um parametro, que eh o nome do arquivo */
    if (argc < 2) {
        fprintf (stderr, "Sintaxe: %s nomeDoArquivoDeEntrada\n", argv[0]);
        return 1;
    }
    /* Abrindo o arquivo de entrada */
    arquivo = fopen (argv[1], "rt");
    if (arquivo == NULL) {
        fprintf (stderr, "Arquivo %s nao foi aberto\n", argv[1]);
        return 1;
    }
    /* Lendo o arquivo de entrada */
    nLinha = 0;
    while (fgets (linha, sizeof(linha), arquivo) != NULL) {
        if (nLinha >= MAXLINHAS)
            break;
        /* Cada linha eh alocada... */
        linhasDoArquivo[nLinha] = strdup (linha);
        nLinha++;
    }
    fclose (arquivo);
    /* Agora imprimindo o arquivo lido */
    for (i = 0; i < nLinha; ++i) {
        fputs (linhasDoArquivo[i], stdout);
    }
    /* Uma vez alocadas as linhas, vamos desaloca-las */
    for (i = 0; i < nLinha; ++i) {
        free (linhasDoArquivo[i]);
    }
    return 0;
}

Na prática, você redimensionaria o array de linhas dinamicamente (isso é uma técnica um pouco mais avançada, que fica como exercício).

Opa entendo todas as suas recomendações, mas é um problema de lógica eu não estou programando “comercialmente”, obrigado pelas dicas vou estudar essa técnica.