从文件中扫描带有空格的字符串,同时在同一行中扫描其前后的数字
Scanning a string with spaces from a file while also scanning numbers before and after it in the same line
我实际上是新手,所以我在学习时遇到了一个错误,我实际上是在尝试 fscanf
从文件中然后将其显示在屏幕上一切正常,直到我添加书名 space 在文件中。它显示book.id
很好,但它只显示书的名字,后面的整数变为0。
示例输出:
我的函数:
void display_unsorted(FILE *fptr){
int x;
int lines_num=how_many_lines_in_file(fptr);
fptr=fopen("books.dat","r");
if(fptr==NULL){
printf("this file is not open");}
for(i=0;i<lines_num;i++){
fscanf(fptr,"%d\t%s\t%d\n",&books[i].id,books[i].name,&books[i].quantity);
}
for(x=0;x<lines_num;x++){
printf("%d\t%s\t%d\n",books[x].id,books[x].name,books[x].quantity);
}
fclose(fptr);
}
fscanf
会在发现空白时停止阅读 space,您可以使用以下方法覆盖此行为:
fscanf(fptr,"%d %99[^0-9] %d\n", &books[i].id, books[i].name, &books[i].quantity);
^^^^^^^^^
正在翻译,将读取最多99个字符的字符串,找到任何数字即停止读取,即从0到9的字符。
我把\t
去掉了,不用了,就算文件里有,一个空白的space就够了。
请注意,这是针对最大大小为 100 个字符的 books[i].name
容器,即 99 个字符加上空终止符,这必须适应您的代码中未显示的容器大小.
另请注意,如果字符串中包含数字,这将无法按预期工作。
假设输入文件中的字段分隔符是<tab>
,OP不清楚,除了调用fscanf()
中的格式字符串,然后
fscanf(fptr,"%d\t%s\t%d\n",&books[i].id,books[i].name,&books[i].quantity);
可以更改为:
fscanf( fptr,"%d %[^\t] %d",
&books[i].id,
books[i].name,
&books[i].quantity );
其中 'set' 格式说明符:%[^\t]
将继续输入字符,直到遇到 <tab>
。 <tab>
将留在输入流中,但是,下面的 space 将消耗 white space
(%d
也是如此),但是 space更具可读性。
如前所述,strchr
可用于查找第一个 space,strrchr
可用于查找最后一个 space。这些指针之间的区别在于名称中的字符。
sscanf
可用于解析前导和尾随整数。
strncpy
可用于从行内复制名称。
该程序只处理一行。将其包装在 while ( fgets ( line, sizeof line, fptr))
中将处理文件中的每一行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( void) {
char line[200] = "123 firstname lastname 456\n";
char name[120] = "";
char *first = line;
char *last = line;
int leading = 0;
int trailing = 0;
int valid = 1;
int span = 0;
int result = 0;
if ( ( first = strchr ( line, ' '))) {
if ( ( last = strrchr ( line, ' ')) && last > first) {
result = sscanf ( line, "%d", &leading);
result += sscanf ( last, "%d", &trailing);
if ( 2 != result) {
fprintf ( stderr, "two numbers needed\n");
valid = 0;
}
while ( ' ' == *first) {
++first;//skip leading space
}
while ( ' ' == *last) {
--last;//skip trailing space
}
span = 1 + last - first;//characters in name
if ( span < sizeof name) {
strncpy ( name, first, span);
name[span] = 0;
}
else {
fprintf ( stderr, "name is too long\n");
valid = 0;
}
}
else {
fprintf ( stderr, "two spaces needed\n");
valid = 0;
}
}
else {
fprintf ( stderr, "spaces needed\n");
valid = 0;
}
if ( valid) {
printf ( "name %s\n", name);
printf ( "leading number %d\n", leading);
printf ( "trailing number %d\n", trailing);
}
return 0;
}
我实际上是新手,所以我在学习时遇到了一个错误,我实际上是在尝试 fscanf
从文件中然后将其显示在屏幕上一切正常,直到我添加书名 space 在文件中。它显示book.id
很好,但它只显示书的名字,后面的整数变为0。
示例输出:
我的函数:
void display_unsorted(FILE *fptr){
int x;
int lines_num=how_many_lines_in_file(fptr);
fptr=fopen("books.dat","r");
if(fptr==NULL){
printf("this file is not open");}
for(i=0;i<lines_num;i++){
fscanf(fptr,"%d\t%s\t%d\n",&books[i].id,books[i].name,&books[i].quantity);
}
for(x=0;x<lines_num;x++){
printf("%d\t%s\t%d\n",books[x].id,books[x].name,books[x].quantity);
}
fclose(fptr);
}
fscanf
会在发现空白时停止阅读 space,您可以使用以下方法覆盖此行为:
fscanf(fptr,"%d %99[^0-9] %d\n", &books[i].id, books[i].name, &books[i].quantity);
^^^^^^^^^
正在翻译,将读取最多99个字符的字符串,找到任何数字即停止读取,即从0到9的字符。
我把\t
去掉了,不用了,就算文件里有,一个空白的space就够了。
请注意,这是针对最大大小为 100 个字符的 books[i].name
容器,即 99 个字符加上空终止符,这必须适应您的代码中未显示的容器大小.
另请注意,如果字符串中包含数字,这将无法按预期工作。
假设输入文件中的字段分隔符是<tab>
,OP不清楚,除了调用fscanf()
中的格式字符串,然后
fscanf(fptr,"%d\t%s\t%d\n",&books[i].id,books[i].name,&books[i].quantity);
可以更改为:
fscanf( fptr,"%d %[^\t] %d",
&books[i].id,
books[i].name,
&books[i].quantity );
其中 'set' 格式说明符:%[^\t]
将继续输入字符,直到遇到 <tab>
。 <tab>
将留在输入流中,但是,下面的 space 将消耗 white space
(%d
也是如此),但是 space更具可读性。
如前所述,strchr
可用于查找第一个 space,strrchr
可用于查找最后一个 space。这些指针之间的区别在于名称中的字符。
sscanf
可用于解析前导和尾随整数。
strncpy
可用于从行内复制名称。
该程序只处理一行。将其包装在 while ( fgets ( line, sizeof line, fptr))
中将处理文件中的每一行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( void) {
char line[200] = "123 firstname lastname 456\n";
char name[120] = "";
char *first = line;
char *last = line;
int leading = 0;
int trailing = 0;
int valid = 1;
int span = 0;
int result = 0;
if ( ( first = strchr ( line, ' '))) {
if ( ( last = strrchr ( line, ' ')) && last > first) {
result = sscanf ( line, "%d", &leading);
result += sscanf ( last, "%d", &trailing);
if ( 2 != result) {
fprintf ( stderr, "two numbers needed\n");
valid = 0;
}
while ( ' ' == *first) {
++first;//skip leading space
}
while ( ' ' == *last) {
--last;//skip trailing space
}
span = 1 + last - first;//characters in name
if ( span < sizeof name) {
strncpy ( name, first, span);
name[span] = 0;
}
else {
fprintf ( stderr, "name is too long\n");
valid = 0;
}
}
else {
fprintf ( stderr, "two spaces needed\n");
valid = 0;
}
}
else {
fprintf ( stderr, "spaces needed\n");
valid = 0;
}
if ( valid) {
printf ( "name %s\n", name);
printf ( "leading number %d\n", leading);
printf ( "trailing number %d\n", trailing);
}
return 0;
}