【问题标题】:Reading both string and integer from a text file从文本文件中读取字符串和整数
【发布时间】:2013-03-09 01:59:43
【问题描述】:

假设我有一个文件看起来像这样

51.41 52.07 52.01 51.22 50.44 49.97 Coal Diggers
77.26 78.33 78.29 78.12 77.09 75.74 Airplane Flyers
31.25 31.44 31.43 31.09 31.01 30.92 Oil Fracting and Pumping
52.03 12.02 12.04 22.00 31.98 61.97 Big Bank
44.21 44.32 44.29 43.98 43.82 43.71 Rail Container Shipping
93.21 93.11 93.02 93.31 92.98 92.89 Gold Bugs

我想使用 fscanf 读取这个文件中的单词,将数字放入浮点数组中,将单词放入字符串数组中。但是,经过几个小时的艰苦思考,我仍然无法弄清楚如何解决这件事。

void dataInsert (COMPANY* company1, COMPANY* company2, COMPANY* company3, COMPANY* company4, COMPANY* company5, COMPANY* company6)
{
//Function Declaration
FILE* spData;
float number;
char* name[20];

//Statement
if ((spData = fopen("dataFile","r")) == NULL)
{
    fprintf(stderr, "ERROR OPENING!!");
    exit (1);
}

int i = 0;
int numCount = 0;
int lineCount = 0;
while (fscanf(spData, "%f", &number) != EOF)
{
    if(isdigit(number))
    {
        if (lineCount == 0)
        {
            company1 -> stock_price[i] = number;
        }
        else if (lineCount == 1)
        {
            company2 -> stock_price[i] = number;
        }
        else if (lineCount == 2)
        {
            company3 -> stock_price[i] = number;
        }
        else if (lineCount == 3)
        {
            company4 -> stock_price[i] = number;
        }
        else if (lineCount == 4)
        {
            company5 -> stock_price[i] = number;
        }
        else if (lineCount == 5)
        {
            company6 -> stock_price[i] = number;
        }

        numCount++;
        i++;
        if (numCount == 6)
        {
            lineCount++;
            numCount = 0;
            i = 0;
        }
    }
}//while
fclose (spData);
}//dataInsert

我不知道如何处理每行末尾的字符串。我想把这些字符串放在结构公司-> 名称 [10] 中。这些数据在一个文本文件中。

【问题讨论】:

  • 您确定要将值读取为整数而不是浮点吗?另外,请告诉我们what you have tried
  • 这些是文件中的实际<br> 标签吗?这个文件是 XML 还是 HTML 还是什么?也许您应该使用解析库?如果文件正是您在此处显示的格式,则可以使用 C 对其进行解析,但脚本语言会更容易... Python 将是我的选择。
  • 您的文件总是这样组织吗?字符串前面有相同数量的数字吗?或者你必须检测你正在阅读的内容是数字还是字符串?
  • scanf 不是一种非常可靠的文件读取方式,因为即使格式有所改变,它也会失败。
  • @Douglas B. Staple 那你有什么推荐的?

标签: c string scanf


【解决方案1】:

我建议不要使用fscanf,而是使用fgets 来获取线路。然后在该行使用sscanf 获取数值,并搜索第一个字母字符以了解字符串的开始位置(例如使用strspn)。

类似这样的:

char line[256];

while (fgets(line, sizeof(line), fp) != NULL)
{
    /* Get the numbers */
    float numbers[6];
    sscanf(line, "%f %f %f %f %f %f",
        &numbers[0], &numbers[1], &numbers[2],
        &numbers[3], &numbers[4], &numbers[5]);

    /* Where do the numbers end... */
    size_t numbers_end = strspn(line, "1234567890. \t");

    /* And get the name */
    char *name = line + numbers_end;

    /* Do something with the numbers and the name */
}

【讨论】:

  • 感谢您的回复,但很遗憾,我不能使用 sscanf,因为这是学校作业的一部分,所以我必须根据我在课堂上学到的知识来做。
  • @ProgrammingNerd 永远不要害怕“跳出框框思考”...您可以做两种解决方案,一种是在分配字面意思之后,然后列出可能的缺点通过解决任务但没有缺点的解决方案。
  • @ProgrammingNerd 并不是说​​我的解决方案本身没有缺点,所有解决方案都有利有弊,包括我的。
  • 是的,我总是尝试以多种方式解决问题,尽管这不是最好的解决方案。这就是让编程如此有趣和有趣的原因!哈哈
【解决方案2】:

如果文件正是该格式,您可以轻松使用scanf()。这是一些可以帮助您入门的代码;这个我没有测试过,你需要填写一些缺失的东西。

#include <ctypes.h>  // for isspace()
#include <stdio.h> // for scanf(), getchar(), and EOF

char c2d[MAX_LINES][MAX_LENGTH_STRING_PER_LINE];
char *pstr;
float f2d[MAX_LINES][6]; // 6 floats per line
float *p;
int c, current_line_number;
char ch;
FILE *input;

input = fopen(...);
if (!input)
    ... handle the error

for (current_line_number = 0; ; ++current_line_number)
{
    // handle each line of input

    // first read 6 float values
    p = f2d + current_line_number;
    c = fscanf(input, "%f %f %f %f %f %f", p + 0, p + 1, p + 2, p + 3, p + 4, p + 5);
    if (c != 6)
        ... handle the error here

    // next grab string; stop at '<' or end of line or EOF
    pstr = c2d + current_line_number;
    for (;;)
    {
        ch = fgetc(input);
        if (ch == EOF || ch == '<' || ch == '\n')
        {
            *pstr = '\0';
            break;
        }
        *pstr++ = ch;
    }
    if (ch == '<')
    {
        // char was '<' so throw away rest of input line until end of line
        for (;;)
        {
            if (ch == EOF || ch == '\n')
                break;
            ch = fgetc(input);
        }
    }
    for (;;)
    {
        // eat up any white space, including blank lines in input file
        if (ch == EOF || !isspace(ch))
            break;
        ch = fgetc(input);
    }
    // once we have hit end of file we are done; break out of loop
    if (ch == EOF)
        break;
}

fclose(input);

我没有使用scanf() 来读取行尾的字符串,因为它会在遇到空格时停止,并且您的字符串值中有空格。

如果输入文件不总是六个浮点值,您将需要编写代码以一次调用一个浮点数 scanf(),直到遇到无法解析为浮点数的内容,并且您需要使浮点数组的宽度足以处理每行允许的最大浮点数。

祝你好运。

【讨论】:

  • fscanf 是用来代替scanf 的,对吧?输入不是来自标准输入,而是来自文件。
  • 当然,还有fgetc() 而不是getchar()。我改变了答案。
  • 如果我使用scanf,它只是跳过每行末尾的字符串吗?
  • 根据scanf() 的手册页,格式代码%s 读取任何非空白字符序列,然后在遇到空白字符时停止。由于公司名称中可以包含空格,因此我认为循环直到完成而不是尝试让scanf() 做我们想做的事情更容易。当您将scanf()%f 格式代码一起使用时,它将返回一个0 表示输入不能作为浮点数工作,并且浮点数中会有一些无意义的值......可能是0 或垃圾,我没有检查。喜欢的可以试试。
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多