Так что я решил продолжить писать почти полную программу для вашей проблемы. Таким образом, я обновил этот ответ полным примером того, как использовать мой оригинальный ответ в программе. Ниже кода моего исходного ответа приведен фактический код работающей программы.
Для вашего кода я не думаю, что имя и телефон "телефонной книги" должны быть массивом, но должны указывать намассивы символов. Это потому, что если у вас есть большая программа, даже если вы даете размер, который всегда больше необходимого размера, или работаете с версией «c», которая позволяет динамическое выделение массива во время выполнения, вы можете столкнуться с проблемой исчерпаниястека памяти.
Тем не менее, этот код ниже является примером и предназначен для анализа только одной строки. В реальном случае вы должны корректно изменить код, чтобы использовать его в цикле. Для процедур, вы просто ищите местоположение ":". Если вы нашли это, ищите местоположение нулевого символа (конец строки). Я поместил комментарии в коде, поэтому я не буду здесь много объяснять.
Кроме того, вам следует подумать о том, чтобы pb был динамическим с помощью calloc () и realloc (). Кроме того, calloc () и realloc () не всегда работают. Вы также можете использовать malloc (), но вы должны сами ввести нулевой символ.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct phonebook{
char * name;
char * phone;
};
int main(void) {
char * line = "John:789-654-3210";
char c;
// search for the :
struct phonebook pb[1];
int dotloc = -1;
int endloc = 0;
int recordIndex = 0;
// Find the dot first
// and then end line.
// This could be done in one loop
// But split into two
for ( int i = 0; ; i++) {
if( line[i] == ':' ) {
dotloc = i;
break;
}
if( line[i] == '\0' ) break;
}
// If found : then that is valid
if ( dotloc > -1 ){
for( int i = dotloc + 1; ; i++){
if( line[i] == '\0' ){
endloc = i;
break;
}
}
// Positioning
// If : is at pos, there is 5 char in the string
// add + for null char.
// If : is at 0 there isn't a char but when calloc still need one for the null char. Empty string.
pb[recordIndex].name = (char*) calloc(dotloc + 1, sizeof(char));
// If : is at 5 and end is at 10, there is only 4 char in between but add keep five because of end char.
pb[recordIndex].phone = (char*) calloc(endloc - dotloc, sizeof(char));
// Memory allocation fail.
// Do something else.
if( pb[recordIndex].name == NULL ) return 1;
if( pb[recordIndex].phone == NULL ) return 1;
// copy from line[0] to dotloc location as how many chars.
// if dotloc is 0, nothing will be copy.
// null char is already appended by calloc.
memcpy(pb[recordIndex].name, line, dotloc * sizeof(char));
// copy from the location of where dotloc is plus 1
// how many char is base on where endloc is - dotloc
// -1
// If endloc at 1 and dot loc is at 0(next to), nothing to be copy.
memcpy(pb[recordIndex].phone, &line[dotloc + 1], (endloc - dotloc - 1));
recordIndex++;
}
printf("%s\n", pb[0].name);
printf("%s", pb[0].phone);
// Sometimes you need to free memory properly.
// depend on which system you target or your use case.
free(pb[0].name);
free(pb[0].phone);
return 0;
}
Я не буду подробно объяснять, что делает каждая функция в программе, как ключевой момент, уже упомянутый выше, и на это может потребоваться несколько часов. Эта программа ниже демонстрирует, как использовать мой оригинальный ответ.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct phoneRecord{
char * name;
char * phone;
};
struct phoneBook{
struct phoneRecord * record;
int length;
int size;
};
struct phoneBook newBook(){
// change init_size to 1 for debugging
int init_size = 30;
static size_t recordSize = sizeof(struct phoneRecord);
struct phoneBook output;
output.record = (struct phoneRecord*) malloc( init_size * recordSize);
output.length = 0;
output.size = init_size;
return output;
}
void freeBook( struct phoneBook * pb){
for ( int i = 0; i < pb->length; i++ ){
free(pb->record[i].name);
free(pb->record[i].phone);
}
free(pb->record);
pb->record = NULL;
pb->length = 0;
pb->size = 0;
}
// 0 for success
// 1 for error
int increaseBookSize(struct phoneBook * pb){
if ( pb == NULL ) return 1;
static size_t recordSize = sizeof(struct phoneRecord);
const int newSize = pb->size * 2;
if ( newSize == 0 ) return 1;
struct phoneRecord * tempPointer = (struct phoneRecord*) realloc(pb->record, newSize * recordSize);
if ( tempPointer != NULL ) {
pb->record = tempPointer;
pb->size = newSize;
return 0;
}
return 1;
}
// Return - 1 for error.
// Return 0 for no record found or no dot.
// Return 1 for record found.
int getRecord( const char * line, struct phoneRecord * pr){
// Null check
if ( pr == NULL ) return -1;
int dotloc = -1;
int endloc = 0;
for ( int i = 0; ; i++) {
if( line[i] == ':' ) {
dotloc = i;
break;
}
if( line[i] == '\0' ) break;
}
if ( dotloc > -1 ){
for( int i = dotloc + 1; ; i++){
if( line[i] == '\0' ){
endloc = i;
break;
}
}
pr->name = (char*) calloc(dotloc + 1, sizeof(char));
pr->phone = (char*) calloc(endloc - dotloc, sizeof(char));
if( pr->name == NULL ) return -1;
if( pr->phone == NULL ) return -1;
memcpy(pr->name, line, dotloc * sizeof(char));
memcpy(pr->phone, &line[dotloc + 1], (endloc - dotloc - 1));
return 1;
}
return 0;
}
int main(void) {
struct phoneBook pb = newBook();
const char * fileName = "test.txt";
char * line = NULL;
FILE *fp;
size_t len = 0;
int recordReturnCode;
fp = fopen(fileName, "r");
if (fp == NULL){
printf("Couldn't open file %s.\n", fileName);
return 1;
}
while (getline(&line, &len, fp) != -1) {
if ( pb.length >= pb.size ) {
if ( increaseBookSize(&pb) != 0 ) {
printf("Something is wrong with getting more memory for the book. However, still print out what already got.\n");
break;
}
}
recordReturnCode = getRecord(line, &pb.record[pb.length]);
if ( recordReturnCode == 1 ) pb.length++;
if ( recordReturnCode == -1 ){
printf("Something is wrong with getting the record. Clean up and exit.\n");
freeBook(&pb);
free(line);
return 1;
}
}
free(line);
printf("Print phonebook size for debuging. Size: %d\n", pb.size);
printf("Read file '%s' and found %d records. Printing each record.\n\n", fileName, pb.length);
for ( int i = 0; i < pb.length; i++ ){
printf("Record: %d | Name: %s | Phone: %s", i, pb.record[i].name, pb.record[i].phone);
}
freeBook(&pb);
printf("\n\nChecking book after free. Length: %d, Size: %d", pb.length, pb.size);
if ( pb.record == NULL ) printf("\nPhonebook free properly, record is NULL.");
return 0;
}
test.txt content:
John:789-654-3210
Bill:852-123-4567
This is not a valid record
Amy:963-321-0000
AfterEmpty:123-456-789
:###-###-####
noNumber:
Kevin:123-123-1234