Используйте указатель для ввода строк из файла в двумерный массив символов в C - PullRequest
0 голосов
/ 19 марта 2020

У меня проблемы с вводом строк из файла в мой массив символов 2D (массив строк). Мне нужно сделать это с указателями, однако, это производит странный беспорядок последних и вторых до последних слов. Кроме того, я не могу использовать функции библиотеки строк.

Вот мой код:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fin, *fout;
    char lineRead[20], arr2[20][20];
    int i, j, k, len;


    fin = fopen("cp4in_1.txt","r");
    if (fin){
        while(fscanf(fin,"%s",&lineRead) != EOF){
            char *pointer = lineRead;
            for (k = 0; lineRead[k] != '\0'; k++);
            for (i = 0; i < 4; i++){
                for (j = 0; j < k; j++){
                    arr2[i][j] = *pointer;
                    pointer++;
                }
            }
        }
    }
    else{
        printf("Couldn't find file.\n");
    }
}

Вот cp4in_1.txt:

ABCDE
PQRSTFG
acegikmoqsuwyz
bdfhjlnprtvx

Результат I Я должен иметь arr2 содержать массив строк, говорящих "ABCDE" , "PQRSTFG" , "acegikmoqsuwyz" и "bdfhjlnprtvx" .

Ответы [ 3 ]

0 голосов
/ 19 марта 2020

Самая большая проблема, с которой вы сталкиваетесь - это попытка линейно-ориентированного ввода с помощью функции отформатированный ввод . (и вы используете его неправильно) Использование fscanf (семейство функций scanf) полно подводных камней для нового C программиста. Пока вы не знаете, что это такое, избегайте их использования и вместо этого используйте линейно-ориентированные функции ввода fgets() или POSIX getline(), которые гарантируют, что вся строка ввода используется каждый раз.

В вашем случае массив lineRead распадается на указатель при доступе, C11 Standard - 6.3.2.1 Другие операнды - L-значения, массивы и указатели функций (p3) , поэтому вы используете &lineRead неправильно (в результате параметр для fscanf() с типом char ** вместо правильного char*). '&' не требуется, поскольку lineRead уже является указателем , поэтому правильное использование будет:

  while(fscanf(fin,"%19s",lineRead) == 1){

( примечание: , вы также должны предоставить модификатор field-width для ограничения чтения символов до значения, которое поместится в lineRead - включая символ с нулевым окончанием . В противном случае вы используете fscanf() больше не будет безопаснее, чем использование gets() - который был полностью удален из C11)

Это лишь одна из многих ловушек, ожидающих укуса, используя семейство scanf.

Вместо этого, используя строково-ориентированную функцию ввода, вы можете сделать:

#include <stdio.h>

#define ROWS   20
#define COLS ROWS   /* if you need a constant, #define one (or more) */

int main (int argc, char **argv) {

    char arr[ROWS][COLS];
    size_t n = 0;
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }

    /* while array not full, read line into array */
    while (n < ROWS && fgets (arr[n], COLS, fp)) {
        char *p = arr[n];           /* pointer to start of string */
        do {                        /* loop until '\n' found */
            if (*p == '\n')  
                *p = 0;             /* overwrite with nul-terminating char */
        } while (*p && *++p);
        n++;                        /* increment line counter */
    }

    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);

    for (size_t i = 0; i < n; i++)  /* output stored lines */
        printf ("line %2zu : %s\n", i, arr[i]);
}

Используя линейно-ориентированную функцию ввода, '\n' считывается из ввода и включается в заполненный буфер. Ваша единственная работа - удалить завершающий '\n' из буфера. Обычно это делается, например, с arr[n][strcspn(arr[n], "\n")] = 0;, но поскольку вы не можете использовать string.h, простой l oop будет работать очень хорошо.

Пример использования / Вывод

С вашим входным файлом в dat/cp4int_1.txt вы передадите имя файла программе в качестве первого аргумента и получите следующий вывод:

$ ./bin/readcp4int_1 dat/cp4int_1.txt
line  0 : ABCDE
line  1 : PQRSTFG
line  2 : acegikmoqsuwyz
line  3 : bdfhjlnprtvx

Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы .

0 голосов
/ 19 марта 2020

Основная проблема заключалась в том, что вы просматривали arr [i] внутри цикла while, и не забывайте ставить '\ 0' в конце каждой строки. Кроме того, вы объявили указатель на символ несколько раз в то время как l oop, это тоже ошибка.

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fpin, *fpout;
    char lineRead[20], arr2[20][20], *pointer;
    int i = 0, j, k, len;


    fpin = fopen("cp4in_1.txt","r");
    if (fpin){
        while(fscanf(fpin,"%s", lineRead) != EOF){
        pointer = lineRead;
        for (k = 0; lineRead[k] != '\0'; k++);
        for(j = 0; j < k; j++){
            arr2[i][j] = *pointer;
            pointer++;
        }
        arr2[i][j+1] = '\0';//place zero char at the end of the string
        i++;
        if(i >= 4)
            break;
        }
    }
    else{
        printf("Couldn't find file.\n");
    }
    //output the result
    for(i = 0; i < 4; i++){
    printf("%s\n", arr2[i]);
    }

    return 0;
}

Вывод:

ABCDE
PQRSTFG 
acegikmoqsuwyz
bdfhjlnprtvx
0 голосов
/ 19 марта 2020

вы всегда должны заканчивать свою строку с \0 так:

          for (i = 0; i < 4; i++){
                for (j = 0; j < k; j++){
                    arr2[i][j] = *pointer;
                    pointer++;
                }
                arr2[i][j]='\0';
            }

также ваша программа нуждается в небольшом изменении

int main()
{
    FILE* p;
    p = fopen("file.txt", "r+");

    int i = 0, j, k;
    char* pointer, lineRead[20], arr2[20][20];
    if (p != NULL)
    {
        while (!feof(p))
        {
            fscanf(p, "%s", &lineRead);
            for (k = 0; lineRead[k] != '\0'; k++);
            pointer = lineRead;
            for (j = 0; j < k; j++)
            {
                arr2[i][j] = *pointer;
                pointer++;
            }
            arr2[i][j] = '\0';
            i++;
        }
        for (int i = 0; i < 4; i++)
        {
            printf("%s\n", arr2[i]);
        }
    }
    else
    {
        printf("Couldn't find file.\n");
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...