【问题标题】:Read Line By Line Until Integer is Found C逐行读取直到找到整数 C
【发布时间】:2015-05-14 09:06:33
【问题描述】:

尝试创建一个接收文本文件并逐行读取的程序。然后它找到每行上的两个整数并将它们加在一起。然后它将带有原始字符串的新行和总计输出到一个新的文本文件。我需要帮助添加两个整数,从每一行获取它们,然后将新行放入文本文件。

输入文本文件

good morning hello 34 127
ann 20 45
10 11
fun program and you find the same 90 120
news paper said that 56 11
how do you like 20 5
line number 90 34

输出首先看起来像:然后继续

good morning hello 161

代码:

int processTextFile(char * inputFileName, char * outputFileName)
{
   FILE *fp = fopen(inputFileName, "r");//open file to to read
   char buff[1024];
   char *p, *p1;
   int num;
   while (fgets(buff, 1024, fp)!=NULL)
   {
      printf("%s\n", buff);
      while(scanf(buff, "%*[^0-9]%d", &num)== 1)
         printf("%d\n", num);
      //fscanf(fp, "%s", buff);
   }

   return 0;
}

编辑!!!!::

所以现在我已经能够做到这一点。我将如何按产生的数字对其进行排序?例如:

Time is money 52
here I am 3
21

会按顺序输出到一个新的文本文件

here I am 3
21
Time is money 52

【问题讨论】:

  • 建议:检查fopen()是否成功
  • ..并且,如果 fopen() 成功,请在完成后关闭文件。我将 strtok() 取出每个标记,然后尝试进行整数转换。
  • 用新问题编辑。
  • 将新问题写成新问题。编辑已经有答案的旧问题是让我们看不到问题的好方法。
  • 回答新问题:不要在循环内打印,而是将数据添加到数组中。当循环完成对数组的排序并且仅在所有这些之后打印它。

标签: c string file file-io int


【解决方案1】:

我使用 strcspn() 的版本应该可以使用 stdin 进行输入,使用 stdout 进行输出。 (所以你可以这样做executable <textfile >newtextfile

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

int main(void) {
    char line[1000];
    while (fgets(line, sizeof line, stdin)) {
        char *ptr;
        size_t x = strcspn(line, "0123456789");
        if (line[x]) {
            errno = 0;
            int n1 = strtol(line + x, &ptr, 10);
            if (*ptr && !errno) {
                errno = 0;
                int n2 = strtol(ptr, &ptr, 10);
                if (*ptr && !errno) {
                    int n3 = n1 + n2;
                    printf("%.*s%d\n", (int)x, line, n3);
                } else {
                    printf("%s", line); // line includes ENTER
                }
            } else {
                printf("%s", line); // line includes ENTER
            }
        } else {
            printf("%s", line); // line includes ENTER
        }
    }
    return 0;
}

没有错误检查的相同版本

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

int main(void) {
    char line[1000];
    while (fgets(line, sizeof line, stdin)) {
        char *ptr;
        size_t x = strcspn(line, "0123456789");
        int n1 = strtol(line + x, &ptr, 10);
        int n2 = strtol(ptr, &ptr, 10);
        int n3 = n1 + n2;
        printf("%.*s%d\n", (int)x, line, n3);
    }
    return 0;
}

【讨论】:

    【解决方案2】:

    方法应该是:

    1. 打开两个文件,一个用于输入,一个用于输出。
    2. 使用sscanf() 读取输入缓冲区。
    3. 扫描前导字符串,然后扫描两个数字。
    4. 如果之前的sscanf() 失败,只检查两个数字。
    5. 如果上述任一扫描成功,则将总和打印到输出文件。

    一个示例代码,应该是这样的

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
    
            FILE *fpin = fopen("ipfile", "r");//open file to to read
            if (!fpin)
            {
                    printf("Error in ipfile opening\n");
                    exit (-1);
            }
            FILE *fpout = fopen("opfile", "w");//open file to to write
            if (!fpout)
            {
                    printf("Error in opfile opening\n");
                    exit (-1);
            }
            char buff[1024] = {0};
            char str[1024] = {0};
            int num1 =0, num2= 0;
            while (fgets(buff, 1024, fpin)!=NULL)
            {
                    memset(str, 0, sizeof(str));
                    //printf("%s\n", buff);
                    if(sscanf(buff, "%[^0-9]%d %d", str, &num1, &num2)== 3)
                        fprintf(fpout, "%s %d\n", str, (num1+num2));
                    else if (sscanf(buff, "%d %d", &num1, &num2)== 2)
                        fprintf(fpout, "%d\n", (num1+num2));
            }
    
            return 0;
    }
    

    注意:

    上述程序,是一种workaround。如果文件中的数据模式发生更改,则需要进行大量更改才能维护这样的代码。而不是 usinf sscnaf(),为了更好、更健壮的方法,你应该

    1. 从文件中读取该行
    2. 开始标记输入缓冲区 (strtok()) 并检查 ints 作为标记 (strtol())。
    3. 分别保存返回的令牌和ints。
    4. 一旦 strtok() 返回 NULL,您将字符串标记和整数的总和打印到 o/p 文件。

    【讨论】:

      【解决方案3】:

      我不打算完全更改您的代码,所以我只是添加了一些 sn-ps 进行改进。

      int processTextFile(char *inputFileName, char *outputFileName) {
      
           FILE *fp = fopen(inputFileName, "r");
           FILE *out = fopen(outputFileName, "w");
           char line[1024];
      
           if (!fp) {
                perror(inputFileName);
                return;
           }
      
           while (fgets(line, sizeof(line), fp) != NULL) {
                int num1 = 0, num2 = 0;
                char textPart[1024] = "";
                if ( !sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2) {
                     sscanf(line, "%d%d", &num1, &num2);
                }
                fprintf(out, "%s %d\n", textPart, num1 + num2);
           }
           fclose(fp);
           fclose(out);
      }
      

      说明:

      我扫描了文本文件,提取了文本部分和两个ints。由于我注意到ints 位于每行的末尾,因此我只使用了sscanf()

      sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2);
      

      这里,"%[a-zA-Z' ']%d%d" 格式说明符意味着只获取字母和空格。

      由于它只会获取字母和空格,因此输入文件中的"10 11" 行不会被放入num1num2。因为代码首先检查包含字母和空格的字符串。由于 10 和 11 不属于限定类型,因此直接跳过该行。

      这就是我添加if-else 语句的原因,该语句检查 sscanf 是否将任何内容写入内存。如果 sscanf 返回 0,则表示不存在文本部分。只是数字。所以程序会扫描这两个数字。

      if ( !sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2) ) {
          sscanf(line, "%d%d", &num1, &num2);
      }
      

      我还为输入文件添加了文件检查。它检查文件是否不存在或不能被文件流打开。

      if (!fp) {
            perror(inputFileName);
            return;
      }
      

      执行后输出文件的内容如下:

      good morning hello  161
      ann  65
      21
      fun program and you find the same  210
      news paper said that  67
      how do you like  25
      line number  124
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多