【问题标题】:Use a pointer to enter strings from a file into a 2D char array in C使用指针将文件中的字符串输入到 C 中的二维字符数组中
【发布时间】:2020-03-19 18:41:29
【问题描述】:

我在将文件中的字符串输入我的二维字符数组(字符串数组)时遇到问题。我需要用指针来做,但是,它会产生最后一个单词和倒数第二个单词的奇怪混乱。另外,我不能使用字符串库函数。

到目前为止,这是我的代码:

#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

我正在寻找的结果应该是 arr2 包含一个字符串数组,上面写着 "ABCDE""PQRSTFG""acegikmoqsuwyz"“bdfhjlnprtvx”

【问题讨论】:

    标签: c arrays string pointers char


    【解决方案1】:

    主要问题是你在 while 循环中循环 arr[i] 并且不要忘记将 '\0' 放在每个字符串的末尾。此外,您在 while 循环中多次声明 char 指针,这也是错误。

    #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
    

    【讨论】:

      【解决方案2】:

      您应该始终使用\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;
      }
      

      【讨论】:

        【解决方案3】:

        您面临的最大问题是尝试使用 formatted-input 函数进行 line-oriented 输入。 (而且你用错了) 使用fscanfscanf 系列函数)对于新的 C 程序员来说充满了陷阱。在您知道它们是什么之前,请避免使用它们,而是使用面向行的输入函数 fgets() 或 POSIX getline(),确保每次都使用一整行输入。

        在您的情况下,数组lineRead 在访问时衰减为指针C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3),因此您对&amp;lineRead 的使用是错误的(导致fscanf() 的参数具有char ** 类型而不是正确的@ 987654330@)。不需要'&amp;',因为lineRead 已经是一个指针,因此正确的用法是:

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

        (注意:您还必须提供 field-width 修饰符,以将字符的读取限制为适合 lineRead 的内容 - 包括 nul-终止字符。否则你使用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,因此一个简单的循环就可以正常工作。

        使用/输出示例

        使用dat/cp4int_1.txt 中的输入文件,您可以将文件名作为第一个参数传递给程序并接收以下输出:

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

        查看一下,如果您还有其他问题,请告诉我。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-22
          • 1970-01-01
          相关资源
          最近更新 更多