繁体   English   中英

从文件中读取,C

[英]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,但是,它会在终端中。 此外,我已经验证它只将单词放在分配的位置。

以下建议的代码:

  1. 干净地编译
  2. 执行所需的功能
  3. 正确地将错误消息传递给stderr
  4. 在每个单词后放置一个逗号 + 空格
  5. 使用“#define”来避免代码中的“魔术”数字

现在,建议的代码:

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM