[英]Reading from a file, C
我目前正在开发一个程序,其目标是从文件中获取单词,并将它们存储到一个数组中,同时输出它们是在行的开头还是在行中的单词。 该文件如下所示:在每一行的末尾有一个最后的空格和一个换行符。
abbe able
abet abut
able abbe ably axle
ably abbe able ally
abut abbe abet
aced aces acid aged aped awed axed iced
aces aced acts ages ales apes axes ices
ache achy acme acne acre
achy ache ashy
我目前在终端中工作的代码,输出:
Row: abbe able,
Row: abet abut,
Row: able abbe, ably, axle,
Row: ably abbe, able, ally,
Row: abut abbe, abet,
Row: aced aces, acid, aged, aped, awed, axed, iced,
Row: aces aced, acts, ages, ales, apes, axes, ices,
Row: ache achy, acme, acne, acre,
Row: achy ache, ashy,
但是,当我使用 valgrind 运行它时,我遇到了一个问题,它无法识别行,而是仅输出前 2 个字母作为每行。
Row: abbe able,
ab, abut,
ab, abbe, ably, axle,
ab, abbe, able, ally,
ab, abbe, abet,
ac, aces, acid, aged, aped, awed, axed, iced,
ac, aced, acts, ages, ales, apes, axes, ices,
ac, achy, acme, acne, acre,
ac, ache, ashy,
在它完成输出所有字符后,它会读取以下内容:
*** stack smashing detected ***: terminated
==24==
==24== Process terminating with default action of signal 6 (SIGABRT)
==24== at 0x489818B: raise (raise.c:51)
==24== by 0x4877858: abort (abort.c:79)
==24== by 0x48E23ED: __libc_message (libc_fatal.c:155)
==24== by 0x49849B9: __fortify_fail (fortify_fail.c:26)
==24== by 0x4984985: __stack_chk_fail (stack_chk_fail.c:24)
==24== by 0x1094B0: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/test)
zo, boos, coos, moos, woos, zoom,==24==
==24== HEAP SUMMARY:
==24== in use at exit: 0 bytes in 0 blocks
==24== total heap usage: 19,833 allocs, 19,833 frees, 266,441 bytes allocated
==24==
==24== All heap blocks were freed -- no leaks are possible
==24==
==24== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Aborted (core dumped)
这是代码。 任何帮助将不胜感激!!
int main(){
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity = 19829;
/*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
char word[5];
/*how many times we've changed the character*/
int letterSpot = 0;
/*Four Letter Word Document*/
FILE *flwd = fopen("WordDocuments/Four_Letter_Connections.txt", "r");
if(flwd == NULL){
printf("File Failed");
}
/* is it the first word of the line */
int wordCount = 0;
/* P is a step ahead of c, because otherwise the words get super messed up. */
int p = fgetc(flwd);
/*the character that goes through the file*/
int c = p;
/* So, this is a temporary word, who will store the row, so all of its category folks will be contained within it */
/*This stores all of the words*/
char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*));
int i;
for(i = 0; i < totalWordQuantity; i++){
wordStorage[i] = malloc(sizeof(char) * 5);
}
int nextIsRow = 1;
/* First, take the character */
while(wordCount < totalWordQuantity){
p = fgetc(flwd);
/* Add the character to the word */
word[letterSpot] = (char)c;
/* Allows the letter spot to find the next place into the word */
letterSpot++;
if(c == ' '){
letterSpot = 0;
word[4] = '\0';
strcpy(wordStorage[wordCount], word);
if(nextIsRow == 1){
printf("\nRow: %s", wordStorage[wordCount]);
}
else{
printf(" %s,", wordStorage[wordCount]);
}
if(p == '\n'){
nextIsRow = 1;
p = fgetc(flwd);
}
else{
nextIsRow = 0;
}
wordCount++;
}
c=p;
}
fclose(flwd);
//Frees up word storage
for(i = 0; i < totalWordQuantity; i++){
free(wordStorage[i]);
}
free(wordStorage);
return 0;
感谢您的关注!
一些额外的细节:如果我在if(p == '\n')
行下有 output 的东西,它不会在 valgrind 中 output,但是,它会在终端中。 此外,我已经验证它只将单词放在分配的位置。
以下建议的代码:
stderr
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LEN 1024
int main( void )
{
/*Four Letter Word Document*/
FILE *flwd = fopen( "WordDocuments/Four_Letter_Connections.txt", "r" );
if( flwd == NULL )
{
perror( "fopen Failed" );
exit( EXIT_FAILURE );
}
size_t rowCount = 0;
char lineBuf[ MAX_LINE_LEN ];
while( fgets( lineBuf, MAX_LINE_LEN, flwd ) )
{
// remove trailing '\n'
lineBuf[ strcspn( lineBuf, "\n" ) ] = '\0';
rowCount++;
printf( "Row: %4zu ", rowCount );
char *token = strtok( lineBuf, " " );
while( token )
{
printf( "%s, ", token );
token = strtok( NULL, " " );
}
printf( "\n" );
}
fclose( flwd );
return 0;
}
使用列出的 OP 输入文件运行代码会导致:
Row: 1 abbe, able,
Row: 2 abet, abut,
Row: 3 able, abbe, ably, axle,
Row: 4 ably, abbe, able, ally,
Row: 5 abut, abbe, abet,
Row: 6 aced, aces, acid, aged, aped, awed, axed, iced,
Row: 7 aces, aced, acts, ages, ales, apes, axes, ices,
Row: 8 ache, achy, acme, acne, acre,
Row: 9 achy, ache, ashy,
好吧,你的代码有点乱。 而且,它很难阅读。 所以,我建议尝试清理你的代码并做一些事情,这些只是必要的。 我正在提供一段与您的代码相同的代码。 看一下,并尝试使您的代码更好,并且可能在此过程中您会清楚哪里出了问题:
更新:
感谢@AnttiHaapala,正如他所指出的那样。 我正在使用char ch = fgetc()
,而fgetc()
返回int
,这会导致特定编译器出现问题(将char
声明为无符号)。
这是更新的代码。
#include <stdio.h>
#include <stdlib.h>
#define BUF_SIZE 1024
int readLine(FILE *fp, char *buf) {
int i = 0;
int ch = fgetc(fp); // as fgetc() returns int
while(ch != '\n' && ch != EOF) {
buf[i++] = (char)ch; // cast 'ch' as 'char'
ch = fgetc(fp);
}
buf[i] = '\0';
// returns true if EOF is not found
// i.e. if line-break is the reason to terminate
return (ch == '\n');
}
int main() {
// declaring a buffer to hold a single line contents
char buf[BUF_SIZE];
char input[] = "input.txt";
FILE *fp = fopen(input, "r");
if(fp == NULL) {
printf("Can not open file\n");
exit(1);
}
int isLineBreak = 0; // by default declaring it false
do {
isLineBreak = readLine(fp, buf); // checking end line status
printf("%s\n", buf);
// run loop as long as you find line-break
// break only if you find EOF
} while(isLineBreak);
fclose(fp);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.