c-如何从头开始打印一行



我一直在编写一个程序,将数据写入文本文件,并在c中练习数据处理,然后从中找到数据,每个数据都存储为行。有行,数据逐行存储,例如:

学生姓名 学生姓氏学生电话等

当我输入"0"时;学生姓名";它开始打印而不打印姓名本身,打印后面的内容,如果我搜索姓氏,也会发生同样的情况,只会打印出手机。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
FILE *filePtr;
filePtr=fopen("std.txt","r");
char char_input[50];
char string[500];

printf("%s","Please give an input of the phone numbern");
scanf("%s",char_input);
while(!feof(filePtr)){
fscanf(filePtr,"%s",string);
if(strcmp(string, char_input)== 0){
fgets(string,500,filePtr);
puts(string);
}
}
fclose(filePtr);
}

文本文件:

Andrew Brooks 865 965 55

输入:

Andrew

输出:

Brooks 865 965 55

期望输出:

Andrew Brooks 865 965 55

而不是错误地使用feof()fscanf(filePtr,"%s", ...来错误地读取。使用fgets()读取文件的并转换为字符串

  • 测试fgets()的返回值以查看是否发生了输入。

  • 使用strstr()string中查找匹配的子字符串。

示例:

while (fgets(string, sizeof string, filePtr)) {
if (strstr(string, char_input)){
fputs(string, stdout);
}
}

函数feof只会告诉您以前的输入操作是否已经遇到文件末尾。它不会告诉您现在是否已到达文件末尾,因此下一次输入操作将失败。该功能无法预测对fscanffgets的下一次输入操作是否会失败。因此,通常不应将其用作循环条件。请参阅此问题以获取更多信息:为什么"while(!feof(file))"总是错误的?

在您的情况下,feof可能返回false,并且由于遇到文件末尾,对fscanf的后续函数调用可能返回EOF。在这种情况下,您发布的代码将忽略fscanf的返回值,并表现为fscanf已经成功,并且您发布的编码将尝试处理不存在的输入。这可能会导致一个错误。

因此,您不应该使用函数feof来确定是否应该继续循环,而应该检查输入函数的返回值。

你可以这样重写你的循环:

while ( fscanf(filePtr,"%s",string) == 1 ) {
if ( strcmp(string, char_input ) == 0 ) {
fgets( string, 500, filePtr );
puts( string );
}
}

这将解决上述不检查CCD_ 16的返回值的问题。然而,根据确切的输入,函数fgets也可能因遇到文件末尾而失败。因此,最好您的程序也检查函数fgets的返回值,而不是简单地假设函数成功。

另一个问题是线路

puts(string);

将只打印string的内容,即" Brooks 865 965 55"。但是,您还想打印"Andrew",它被fscanf函数调用读取,但同时被fgets函数调用覆盖。最简单的解决方案是在它被覆盖之前将其打印出来。然而,如果用户搜索"Brooks"而不是"Andrew",这将不起作用,因为单词"Andrew"将在先前循环迭代中已经被丢弃。这是因为在循环中调用fscanf(filePtr,"%s",string)不会在每次循环迭代中读取一行输入,而是在每次循环循环迭代中只读取一个字(这不是很有意义)。

使用fscanf(filePtr,"%s",string)逐字逐句读取输入文件的另一个后果是,您将无法找到与电话号码"865 965 55"匹配的号码。这是因为您的程序将首先从输入文件读取CCD_;单词";与搜索字符串不相同。然后它将读取"965"并确定相同的事情。它对"55"也是如此。

最好的解决方案可能是重新设计循环,使其在每次循环迭代中始终只读取一行输入,而不是每次循环迭代仅读取一个单词。在读取一行输入后,您可以通过将该行拆分为"来解析该行;名字"姓氏";以及";电话号码";使用函数CCD_ 33。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *filePtr;
char search_string[50];
char line[200];
//open input file
filePtr = fopen( "std.txt", "r" );
if ( filePtr == NULL )
{
fprintf( stderr, "unable to open input file!n" );
exit( EXIT_FAILURE );
}
//prompt user for input
printf( "Please enter search string: " );
//Note that the following code now uses "fgets" instead
//of "fscanf", because fscanf will only read a single
//word, when using the "%s" format specifier. This means
//that it would be unable to read the phone number
//"865 965 55" as an input string, because that line
//consists of three "words".
//read exactly one line of input from user
if ( fgets( search_string, sizeof search_string, stdin ) == NULL )
{
fprintf( stderr, "input failure!n" );
exit( EXIT_FAILURE );
}
//remove newline character from input line by
//replacing it with terminating null character
search_string[strcspn(search_string,"n")] = '';
//read exactly one line of input from the input file
//per loop iteration
while ( fgets( line, sizeof line, filePtr ) != NULL )
{
char first_name[50];
char last_name[50];
char phone_number[50];
//attempt to parse input
if (
sscanf(
line,
"%49s %49s %49[^n]",
first_name,
last_name,
phone_number
)
!= 3
)
{
fprintf(
stderr,
"WARNING: skipping line due to parse error!n"
);
continue;
}
//parsing was successful, so we can now search the
//3 individual fields for the search string
if (
strcmp( search_string, first_name   ) == 0
||
strcmp( search_string, last_name    ) == 0
||
strcmp( search_string, phone_number ) == 0
)
{
//remove newline character from input line by
//replacing it with terminating null character
line[strcspn(line,"n")] = '';
//print entire input line of file for user
printf( "%sn", line );
}
}
//cleanup
fclose(filePtr);
}

该程序具有以下行为:

Please enter search string: Andrew
Andrew Brooks 865 965 55
Please enter search string: Brooks
Andrew Brooks 865 965 55
Please enter search string: 865 965 55
Andrew Brooks 865 965 55

请注意,上面的代码并不完美,因为它有以下问题:

  1. 使用fgets时,如果输入行太长,无法放入缓冲区,则程序将不会检测到这一点,尽管在这种情况下,它可能会打印错误消息并退出
  2. 如果任何字段";名字"姓氏";或";电话号码";大于49个字符,代码确实防止了缓冲区溢出(这可能会导致程序崩溃),但它仍然不能正确处理这种情况,例如通过检查这种情况和打印适当的错误消息

但是,出于您的目的,代码可能已经足够了。

解决这些问题的一个更强大的程序是:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
//This function will read exactly one line of input using
//fgets and verify that the line was not too long for the
//input buffer. Note that the buffer size must be two bytes
//longer than the actual string length, because there must
//be space for the newline character and the terminating
//null character. The newline character will be overwritten
//with another terminating null character.
//On success, it will return true. If not further input is
//available due to end-of-file, it will return false.
//Otherwise, the function will not return, but will
//terminate the program with an error message.
bool get_one_line_of_user_input( char *buffer, int buffer_size )
{
char *p;
if ( fgets( buffer, buffer_size, stdin ) == NULL )
{
if ( feof( stdin ) )
{
return false;
}
else
{
fprintf( stderr, "input error!n" );
exit( EXIT_FAILURE );
}
}
p = strchr( buffer, 'n' );
if ( p == NULL )
{
//No newline character was found. This could mean
//that the line was too long to store in the input
//buffer, in which case, the program should quit
//with an error message. However, it could also mean
//that input has been redirected to come from a
//file, and that this file ends with a line without
//a line ending. In that case, the missing newline
//character can be ignored.
if ( !feof( stdin ) )
{
fprintf( stderr, "line too long for buffer!n" );
exit( EXIT_FAILURE );
}
}
else
{
//remove newline character
*p = '';
}
return true;
}
int main()
{
FILE *filePtr;
char search_string[50];
char line[200];
//open input file
filePtr = fopen( "std.txt", "r" );
if ( filePtr == NULL )
{
fprintf( stderr, "unable to open input file!n" );
exit( EXIT_FAILURE );
}
//prompt user for input
printf( "Please enter search string: " );
//read exactly one line of input from user
if ( !get_one_line_of_user_input( search_string, sizeof search_string ) )
{
fprintf( stderr, "input failure!n" );
exit( EXIT_FAILURE );
}
//read exactly one line of input from the input file
//per loop iteration
while ( get_one_line_of_user_input( line, sizeof line ) )
{
char first_name[50];
char last_name[50];
char phone_number[50];
//attempt to parse input
if (
sscanf(
line,
"%49s %49s %49[^n]",
first_name,
last_name,
phone_number
)
!= 3
)
{
fprintf(
stderr,
"WARNING: skipping line due to parse error!n"
);
continue;
}
//verify that none of the fields was too long
if (
strlen( first_name   ) == 49
||
strlen( last_name    ) == 49
||
strlen( phone_number ) == 49
)
{
//At least one buffer is full, and we have no way
//to determine whether the limit was exceeded or whether
//we are merely at the limit, so we must assume that
//the limit was exceeded.
fprintf(
stderr,
"WARNING: skipping line due to field length "
"limit exceeded!n"
);
continue;
}
//parsing was successful, so we can now search the
//3 individual fields for the search string
if (
strcmp( search_string, first_name   ) == 0
||
strcmp( search_string, last_name    ) == 0
||
strcmp( search_string, phone_number ) == 0
)
{
//print entire input line of file for user
printf( "%sn", line );
}
}
//cleanup
fclose(filePtr);
}

相关内容

  • 没有找到相关文章

最新更新