簡體   English   中英

我想將讀取鏈與 C 中的文件分開

[英]I want to separate the read chain from the file in C

我正在嘗試分隔字符串

"CristinaRodriguezRiveraComputacion210302414RamiroSilvaPerezIndustrial217890453PatriciaDuranSanchezCivil215643525RaulColinGranadosComputacion215678342"

從文件中讀取,但是當我分離並打印此字符串時,以下內容未正確分離:

在此處輸入圖像描述

所需 output:

Cristina Rodríguez Rivera Computación 210302414 //模擬每個字符串在 15 個字節的塊內

我不知道代碼有什么問題,我一直試圖弄清楚我的邏輯是否有問題

#include <stdio.h>
#include <errno.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>

typedef struct{
   char name[15];
   char father[15];
   char mother[15];
   char degree[15];
   char id[15];
}Student;


Student al;

int main(){

    FILE*  ent = fopen("DatosEntrada.txt","r");
    FILE*  sal = fopen("longitud.txt","a");

    if(ent != NULL){

        char name[15];
        char father[15];
        char mother[15];
        char degree[15];
        char id[15];

        fseek(ent, 0, SEEK_END);  //getting file length
        int longarch = ftell(ent);
        rewind(ent); //go back to the start

        char dinamic[longarch];

        fscanf(ent,"%s",&dinamic);

        int longitud =  strlen(dinamic);


        int contador=0,iterador=0;
        for(int i=0;i<longarch;i++){

            if( isupper(dinamic[i]) ){

                    if( islower(dinamic[i-1])  && islower(dinamic[i+1])  ){
                        iterator=0;
                        counter++; 

                    }


                    if(counter== 0){ //name
                        iterator=0;
                        name[iterator] = dinamic[i];
                         //printf("%c",name[iterator]);
                        iterator++;

                    }else if(counter== 1){ //father

                        father[iterator] = dinamic[i];
                        //printf("%c",father[iterator] );
                        iterator++;

                    }else if(counter== 2){  //mother

                        mother[iterator] = dinamic[i];
                        //printf("%c",mother[iterator]);
                        iterator++;

                    }else if(counter== 3){  //degree

                        degree[iterator] = dinamic[i];
                        //printf("%c",degree[iterator]);
                        iterator++;

                    }

            }else if( islower(dinamic[i])  ){

                    if(counter== 0){ //name

                        name[iterator] = dinamic[i];
                        //printf("%c",name[iterator]);
                        iterator++;

                    }else if(counter== 1){  //father

                        father[iterator] = dinamic[i];
                        //printf("%c",father[iterator]);
                        iterator++;

                    }else if(counter== 2){ //mother

                        mother[iterator] = dinamic[i];
                        //printf("%c",mother[iterator]);
                        iterator++;

                    }else if(counter== 3){ //degree

                        degree[iterator] = dinamic[i];
                        //printf("%c",degree[iterator]);
                        iterator++;

                    }

            }else if( isdigit(dinamic[i])  ){

                    if( islower(dinamic[i-1]) && isdigit(dinamic[i+1]) ){
                        iterator=0;
                        counter++;

                    }else if(   isupper(dinamic[i+1]) && isdigit(dinamic[i-1]) ){

                        id[iterator] = dinamic[i];

                        //printf("%c",id[iterator]);

                        counter=0;

                        printf("(%s,%s,%s,%s,%s)\n",name,father,mother,degree,id);
                        strcpy(al.name,name);
                        strcpy(al.father,father);
                        strcpy(al.mother,mother);
                        strcpy(al.degree,degree);
                        strcpy(al.id,id);

                        fwrite(&al,sizeof(Student), 1, sal);


                    }

                    if(counter== 4){  //id

                        id[iterator] = dinamic[i];
                       // printf("%c",id[iterator]);
                        iterator++;

                    }

            }

        }


        fclose(ent);
        fclose(sal);

    }else{

       fprintf(stdout, "ERROR: %s", strerror(errno));
    }


}

我認為這里的關鍵問題是,在將字符復制到其中之后,您沒有使用NUL\0 )終止這些字段。

考慮您的第一個字段nombre 您在兩條不同的行上向其寫入數據。 但是你永遠不會在任何地方寫\0 您復制到該字段中的數據是Cristina ,它是 8 個字符,因此該字段的其余 7 個字符只包含 memory 中發生的任何內容。 當您調用printf時,您會得到Cristina ,但沒有\0 ,因此printf只是繼續運行並打印任何內容,直到找到巧合的\0

因此,當您檢測到一個字段的結尾時,您需要在繼續下一個字段之前添加一個\0

不過,還有其他問題。 一個在這里:

        for(int i=0;i<longarch;i++){

            if( isupper(dinamico[i]) ){

                    if( islower(dinamico[i-1])  && islower(dinamico[i+1])  ){
                        iterador=0;
                        contador++; 

                    }

考慮當i == 0第一次通過循環時會發生什么。 isupper調用將返回 true,因為數據的第一個字符是大寫的。 然后它將執行下一行,執行islower(dianamico[i-1])以查看前一個字符是否為小寫。 但是i == 0在這里,所以這是在緩沖區開始之前訪問字節。 i == 0時,您需要避免此檢查。

您還重復代碼以將一個字符復制到每行兩次。 你只需要做一次。 您的代碼應類似於:

while (there is more data) {
  if (it's the start of a new field) {
    add \0 to the end of the current field;
    iterador = 0;
    contador++;
  }
  copy character into current field;
  iterator++;
}
add \0 to the end of the last field;

我試用了您的程序並在打印輸出中獲得了無關數據。 但是,當五個工作字段初始化為零時,確保有效的字符終止符就位,數據看起來很干凈。 以下是添加的附加代碼,以確保字符串包含您想要的數據。

        if(ent != NULL)
    {

        char nombre[15];
        char Paterno[15];
        char Materno[15];
        char carrera[15];
        char matricula[15];

        for (int x=0; x < 15; x++) /* Work field initialization */
            {
            nombre[x] = '\0';
            Paterno[x] = '\0';
            Materno[x] = '\0';
            carrera[x] = '\0';
            matricula[x] = '\0';
        }

試試看。

我很高興您的代碼現在似乎可以工作。

但是,如果是我,我會讓代碼更加模塊化。

我還會使用 state 機器/變量來簡化代碼。

此外,實際讀取數據並將其保存到Alumno結構數組是有意義的。

這是重構的代碼。 注釋如下:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>

#ifdef DEBUG
#define dbgprt(_fmt...)     printf(_fmt)
#else
#define dbgprt(_fmt...)     do { } while (0)
#endif

#define ALLMODE(_cmd) \
    _cmd(NAME) \
    _cmd(FATHER) \
    _cmd(MOTHER) \
    _cmd(CAREER) \
    _cmd(DATE)

#define ENUM(_sym)      MODE_##_sym,
enum {
    ALLMODE(ENUM)
    MODE_MAX
};

#define TAG(_sym)   [MODE_##_sym] = #_sym,
char *tags[MODE_MAX] = {
    ALLMODE(TAG)
};

typedef struct {
    char nombre[15];
    char apPat[15];
    char apMat[15];
    char carrera[15];
    char matricula[15];
} Alumno;

Alumno al;

int icur;                           // current index into dinamico
char *dinamico;                     // buffer for entire file contents

// getstring -- fill in a struct field
void
getstring(char *field)
{
    char *out = field;
    int chr;

    // get and save first char
    chr = dinamico[icur++];
    dbgprt("getstring: FIRST chr='%c'\n",chr);
    *out++ = chr;

    // do we want:
    //   0 -- Cristina
    //   1 -- 210302414
    int dateflg = isdigit(chr);

    while (1) {
        // look at next character
        chr = dinamico[icur];
        if (chr == 0)
            break;
        dbgprt("getstring: PEEK chr='%c'\n",chr);

        int isdig = isdigit(chr);

        // we want a date -- stop if char is _not_ a digit
        if (dateflg) {
            if (! isdig)
                break;
        }

        // we want a name -- stop if char is upper (start of new name) or
        // is a digit (start of a date)
        else {
            if (isupper(chr))
                break;
            if (isdig)
                break;
        }

        *out++ = chr;
        ++icur;
    }

    *out = 0;

    dbgprt("getstring: field='%s'\n",field);
}

int
main(void)
{

    FILE *ent = fopen("DatosEntrada.txt", "r");
    FILE *sal = fopen("longitud.txt", "w");

    if (ent == NULL) {
        fprintf(stdout, "ERROR: %s", strerror(errno));
        return 1;
    }

    // get size of file
    fseek(ent, 0, SEEK_END);
    int longarch = ftell(ent);
    rewind(ent);                    // go back to the start

    // get buffer for entire file
    dinamico = malloc(longarch + 1);
    fscanf(ent, "%s", dinamico);
    longarch = strlen(dinamico);

    int state = MODE_NAME;

    // empty list
    Alumno *list = NULL;
    int count = 0;

    // current record
    Alumno *rec = NULL;

    for (icur = 0; icur < longarch;) {
        if (dinamico[icur] == '\n')
            break;

        dbgprt("main: STATE state=%d (%s)\n",state,tags[state]);

        switch (state) {
        case MODE_NAME:
            // increase size of list
            list = realloc(list,sizeof(*list) * (count + 1));
            rec = &list[count];
            ++count;

            getstring(rec->nombre);
            state = MODE_FATHER;
            break;

        case MODE_FATHER:
            getstring(rec->apPat);
            state = MODE_MOTHER;
            break;

        case MODE_MOTHER:
            getstring(rec->apMat);
            state = MODE_CAREER;
            break;

        case MODE_CAREER:
            getstring(rec->carrera);
            state = MODE_DATE;
            break;

        case MODE_DATE:
            getstring(rec->matricula);
            state = MODE_NAME;
            printf("%s %s %s %s %s\n",
                rec->nombre,rec->apPat,rec->apMat,rec->carrera,rec->matricula);
            fwrite(rec, sizeof(Alumno), 1, sal);
            break;
        }
    }

    fclose(ent);
    fclose(sal);

    free(dinamico);
    free(list);

    return 0;
}

有很多方法可以實現您的目標。 我將此作為一個工作示例,它輸出括號中的版本並顯示如何累積“記錄”(15 個字符寬 * 5)(用於顯示或存儲)...

我希望這將提供材料來更多地了解實現目標的另一種方法。

void showFlds( char flds[][15], int n ) {
    printf( "****\n" );
    for( int i = 0; i < n; i++ )
        printf( "'%-15s'\n", flds[i] );
    printf( "****\n" );
}

int main() {
    char *in =
        "CristinaRodriguezRiveraComputacion210302414"
        "RamiroSilvaPerezIndustrial217890453"
        "PatriciaDuranSanchezCivil215643525"
        "RaulColinGranadosComputacion215678342";

    const int nFlds = 5;
    int fldCnt = 0;
    char fldCopys[5][15];
    int cCnt = 0;

    putchar( '(' );
    bool firstDig = true;
    for( char *cp = in; *cp; cp++ ) {
        if( cp > in && ( isupper( *cp ) || ( isdigit( *cp ) && firstDig ) ) ) {
            fldCopys[ fldCnt++ ][ cCnt ] = '\0';
            if( fldCnt < nFlds ) {
                putchar( ' ' );
            } else {
                printf( ")\n" );
                showFlds( fldCopys, fldCnt );
                putchar( '(' );
                fldCnt = 0;
            }
            cCnt = 0;
        }
        putchar( *cp );
        fldCopys[ fldCnt ][ cCnt++ ] = *cp;
        firstDig = !isdigit( *cp );
    }
    printf( ")\n" );
    fldCopys[ fldCnt++ ][ cCnt ] = '\0';
    showFlds( fldCopys, fldCnt );
    return 0;
}

Output:

(Cristina Rodriguez Rivera Computacion 210302414)
****
'Cristina       '
'Rodriguez      '
'Rivera         '
'Computacion    '
'210302414      '
****
(Ramiro Silva Perez Industrial 217890453)
****
'Ramiro         '
'Silva          '
'Perez          '
'Industrial     '
'217890453      '
****
(Patricia Duran Sanchez Civil 215643525)
****
'Patricia       '
'Duran          '
'Sanchez        '
'Civil          '
'215643525      '
****
(Raul Colin Granados Computacion 215678342)
****
'Raul           '
'Colin          '
'Granados       '
'Computacion    '
'215678342      '
****

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM