我有一个这样的文件:
...
words 13
more words 21
even more words 4
...
(一般格式是一个非数字字符串,然后是一个空格,然后是任意数量的数字和换行符)
我想解析每一行,将单词放入结构的一个字段,将数字放入另一个字段。现在我正在使用一个难看的黑客读取线,而字符不是数字,然后阅读其余的。我相信有一个更清晰的方式。
答案 0 :(得分:6)
编辑:您可以使用pNum-buf获取字符串字母部分的长度,并使用strncpy()将其复制到另一个缓冲区中。请务必在目标缓冲区的末尾添加“\ 0”。我会在pNum ++之前插入这段代码。
int len = pNum-buf;
strncpy(newBuf, buf, len-1);
newBuf[len] = '\0';
您可以将整行读入缓冲区,然后使用:
char *pNum;
if (pNum = strrchr(buf, ' ')) {
pNum++;
}
获取指向数字字段的指针。
答案 1 :(得分:1)
fscanf(file, "%s %d", word, &value);
这将值直接转换为字符串和整数,并应对空格和数字格式等的变化。
修改强>
哎呀,我忘记了单词之间有空格。 在那种情况下,我会做以下事情。 (请注意,它会截断'line'中的原始文本)// Scan to find the last space in the line
char *p = line;
char *lastSpace = null;
while(*p != '\0')
{
if (*p == ' ')
lastSpace = p;
p++;
}
if (lastSpace == null)
return("parse error");
// Replace the last space in the line with a NUL
*lastSpace = '\0';
// Advance past the NUL to the first character of the number field
lastSpace++;
char *word = text;
int number = atoi(lastSpace);
您可以使用stdlib函数解决此问题,但由于您只搜索您感兴趣的字符,因此上述内容可能更有效。
答案 2 :(得分:0)
您可以尝试使用strtok()来标记每一行,然后检查每个标记是一个数字还是一个单词(一旦您拥有标记字符串,这是一个相当简单的检查 - 只需查看标记的第一个字符)。
答案 3 :(得分:0)
假设数字紧跟'\ n'。 你可以读取每一行到字符缓冲区,在整行使用sscanf(“%d”)来获取数字,然后计算这个数字在文本字符串末尾所占的字符数。
答案 4 :(得分:0)
根据字符串的复杂程度,您可能需要使用PCRE库。至少你可以编译一个perl'ish正则表达式来分割你的行。但这可能有点过分了。
答案 5 :(得分:0)
根据描述,这是我要做的:使用fgets()将每一行读作单个字符串(确保目标缓冲区足够大),然后使用strtok()拆分该行。要确定每个标记是单词还是数字,我将使用strtol()来尝试转换并检查错误情况。例如:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/**
* Read the next line from the file, splitting the tokens into
* multiple strings and a single integer. Assumes input lines
* never exceed MAX_LINE_LENGTH and each individual string never
* exceeds MAX_STR_SIZE. Otherwise things get a little more
* interesting. Also assumes that the integer is the last
* thing on each line.
*/
int getNextLine(FILE *in, char (*strs)[MAX_STR_SIZE], int *numStrings, int *value)
{
char buffer[MAX_LINE_LENGTH];
int rval = 1;
if (fgets(buffer, buffer, sizeof buffer))
{
char *token = strtok(buffer, " ");
*numStrings = 0;
while (token)
{
char *chk;
*value = (int) strtol(token, &chk, 10);
if (*chk != 0 && *chk != '\n')
{
strcpy(strs[(*numStrings)++], token);
}
token = strtok(NULL, " ");
}
}
else
{
/**
* fgets() hit either EOF or error; either way return 0
*/
rval = 0;
}
return rval;
}
/**
* sample main
*/
int main(void)
{
FILE *input;
char strings[MAX_NUM_STRINGS][MAX_STRING_LENGTH];
int numStrings;
int value;
input = fopen("datafile.txt", "r");
if (input)
{
while (getNextLine(input, &strings, &numStrings, &value))
{
/**
* Do something with strings and value here
*/
}
fclose(input);
}
return 0;
}
答案 6 :(得分:0)
鉴于描述,我想我会使用这个(现已测试的)C99代码的变体:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
struct word_number
{
char word[128];
long number;
};
int read_word_number(FILE *fp, struct word_number *wnp)
{
char buffer[140];
if (fgets(buffer, sizeof(buffer), fp) == 0)
return EOF;
size_t len = strlen(buffer);
if (buffer[len-1] != '\n') // Error if line too long to fit
return EOF;
buffer[--len] = '\0';
char *num = &buffer[len-1];
while (num > buffer && !isspace(*num))
num--;
if (num == buffer) // No space in input data
return EOF;
char *end;
wnp->number = strtol(num+1, &end, 0);
if (*end != '\0') // Invalid number as last word on line
return EOF;
*num = '\0';
if (num - buffer >= sizeof(wnp->word)) // Non-number part too long
return EOF;
memcpy(wnp->word, buffer, num - buffer);
return(0);
}
int main(void)
{
struct word_number wn;
while (read_word_number(stdin, &wn) != EOF)
printf("Word <<%s>> Number %ld\n", wn.word, wn.number);
return(0);
}
您可以通过为不同问题返回不同的值来改进错误报告。 您可以使用动态分配的内存来处理行的单词部分。 你可以使用比我允许的更长的线条。 您可以向后扫描数字而不是非空格 - 但这允许用户编写“abc 0x123”并正确处理十六进制值。 您可能更愿意确保单词部分中没有数字;这段代码不在乎。