![](/img/trans.png)
[英]in C I want to read in line by line from a file a certain way with the end length of the file changing
[英]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.