Как добавить запятые в массив символов в C - PullRequest
0 голосов
/ 16 февраля 2020

Итак, у меня есть массив символов, который в настоящее время содержит структуру информации о человеке. Например,

struct Person{
char first_name[100];
char last_name[100];
char phone[13];
};

struct Person* arr[] = {("John", "Doe", "831.563.3642"), ("Julie", "Dee", "542.865.4644") };

И я пытаюсь заставить его печатать в файл, чтобы он выглядел следующим образом ...

John, Doe, 831.563.3642
Julie, Dee, 542.865.4644

Пока это мой код ( чтобы попытаться добавить запятые при помещении в файл)

void print(FILE* file_out, struct Person* p1[]){
   size_t len = sizeof(p1) / sizeof(p1[0]);
   for(i = 0; i < len; i++){
      fprintf(file_out, "%s, %s, %s\n", p1[i].first, p1[i].last, p1[i].phone);
   }
}
return;

Ответы [ 2 ]

0 голосов
/ 16 февраля 2020

Возможно, вы делаете вещи намного сложнее для себя, чем нужно. Заполнив struct Person, для получения нужного результата вам просто нужно вывести элементы структуры, разделенные comma и space. Подойдет простой printf, например,

struct Person p1 = { "John", "Doe", "831.563.3642" };
...
printf ("%s, %s, %s", p1.first, p1.last, p1.phone);

Вывод выше будет:

John, Doe, 831.563.3642

Вы никогда не сможете сделать char new[] = ""; - что создает массив new размером 1 с символом '\0'. (неправильный выбор имен, new - это ключевое слово в C ++, его использование в качестве имени переменной следует избегать). Как только вы объявляете и инициализируете массив с помощью automati c длительность хранения размера 1 - его размер равен FIXED - точка и не может быть расширена. Вам нужно было бы динамически выделить хранилище с помощью malloc, чтобы иметь возможность изменить размер хранилища позже с помощью realloc.

Если вы хотите создать дополнительный массив, содержащий значения, разделенные запятыми, то вам необходимо объявите массив с хранилищем для хранения самых больших first_name, last_name и phone изначально, например char buf[100 + 100 + 13 + 4]; (+4 для пары ", ", которую вы также хотите вставить) Теперь вы можете использовать sprintf для простой записи в новый массив.

Ниже приведен короткий пример, который показывает как прямой вывод с printf, так и создание нового массива (buf) с использованием sprintf. Результаты одинаковы независимо от того, выводите ли вы значения, разделенные запятыми, напрямую или сначала сохраняете их в буфере. Функция csvperson() принимает массив назначения и указатель на заполненную структуру в качестве параметра для записи членов структуры, разделенных запятой и пробелом, в массив, например,

#include <stdio.h>

#define MAXNM 100   /* if you need a constant, #define one (or mroe) */
#define MAXPH  13

typedef struct {            /* using a typedef allows you to later omit the */
    char first[MAXNM],      /* 'struct' prefix in your declarations and */
         last [MAXNM],      /* parameter lists */
        phone [MAXPH];
} person;

char *csvperson (char *dest, person *p)
{
    if (!dest)
        return NULL;

    sprintf (dest, "%s, %s, %s", p->first, p->last, p->phone);

    return dest;
}

int main (void) {

    char buf[2 * MAXNM + MAXPH + 4];
    person p1 = { "John", "Doe", "831.563.3642" };

    printf ("direct output : %s, %s, %s\nbuffer output : %s\n", 
            p1.first, p1.last, p1.phone, csvperson (buf, &p1));
}

Пример использования / Вывод

$ ./bin/csvperson
direct output : John, Doe, 831.563.3642
buffer output : John, Doe, 831.563.3642

Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы.


Пример массива

Кому используя те же методы, что и выше, с массивом, вы должны сделать:

int main (void) {

    char buf[2 * MAXNM + MAXPH + 4];
    person p1[] = { {"John", "Doe", "831.563.3642"},
                    {"Jane", "Doe", "832.563.3643"},
                    {"Mary", "Jane", "303.331.3333"} };
    int n = sizeof p1 / sizeof *p1;

    for (int i = 0; i < n; i++)
        printf ("\ndirect output : %s, %s, %s\nbuffer output : %s\n", 
                p1[i].first, p1[i].last, p1[i].phone, csvperson (buf, p1+i));
}

Вы можете просто использовать fprintf для вывода в файл без предварительной буферизации, например,

fprintf (fileptr, "%s, %s, %s\n", p1[i].first, p1[i].last, p1[i].phone);

В общем, не беспокойтесь о комбинировании / объединении / et c .. вещей, которые вы можете просто записать (где бы это ни был файл, терминал и т. Д. c ..)

0 голосов
/ 16 февраля 2020

struct Person * arr [1] эквивалентен Person arr также эквивалентен Person ** arr Я не думаю, что это то, что вы имели в виду. избавьтесь от указателя: D

Теперь некоторые действительно важные вещи о строках ... Функция strlen является причиной № 1 для ошибок переполнения буфера - НИКОГДА не используйте strlen без каких-либо ограничений.

Кроме того, внутренняя длина строки выглядит следующим образом ...

int strlen(char* str) {
    int count = 0;
    while (str[count]) {
        count++;
    }
    return count;
}

замечаете, что это почти ваша функция? Ваша функция может быть изменена на ...

char* makeString(char* str) {
    char out[] = ""
    int count = 0;
    while (str[count]) {
        out[count] = str[count];
        count++;
    }
    out[count] = ',';
    out[count + 1] = 0;
    return out;
}

Давайте поговорим об основных проблемах, связанных с этим, хотя - во-первых, обратите внимание на l oop, которое заканчивается только тогда, когда он находит 0? Это отличный способ сделать ошибку. Все, что кто-то должен сделать, это дать имя слишком долго и бум! нет конца 0.

Теперь представьте, что я вызываю вашу функцию несколько раз подряд ... Вы каждый раз просматриваете строку !!! Другими словами, я перебираю l oop для строки "john". это 4 раза, пока l oop. он также делает char [6] для хранения этих вещей - поскольку john равен 4, а ',' равен 1, а маркер "конца строки" равен 0.

Теперь мы добавим к снова строка мы перебираем "john" в "," и добавляем "Joe". Это означает, что нам нужен новый более длинный символ [] длины 9. Теперь мы перебираем «john» и «doe» в течение 9, пока l oop попадет. Затем мы делаем это снова и снова. Мы перебираем Джона ОГРОМНОЕ количество раз. Слишком много раз.

Теперь о безопасном способе сделать это: D

//Create a string of a known length that can hold all the data
//Now we only need to create a char buffer once instead of multiple times
//In a regular computer, it is better to waste space than CPU time :D (in this case anyway...)
char printString[sizeof(arr.first_name) + 2 + sizeof(arr.last_name) + 2 + sizeof(arr.phone) + 1];
//Remember where we last wrote, and where we are in our current copy
int position = 0;
int i = 0;
//While it is not the end of the string, and we have not gone over the longest possible length...
while (arr[0].first_name[i] && i < sizeof(arr[0].first_name)) {
    //Copy the character
    printString[position] = arr.first_name[i];
    //Move to the next spot in both character buffers
    position++;
    i++;
}
//Add our comma and space
prinstString[position] = ',';
printtString[position + 1] = ' ';
position = position + 2;
int i = 0;
while (arr[0].last_name[i] && i < sizeof(arr[0].last_name)) {
    printString[position] = arr.last_name[i];
    position++;
    i++;
}
prinstString[position] = ',';
printtString[position + 1] = ' ';
position = position + 2;
int i = 0;
while (arr[0].phone[i] && i < sizeof(arr[0].phone)) {
    printString[position] = arr.phone[i];
    position++;
    i++;
}
prinstString[position] = 0;

Теперь о преимуществах.

Мы повторяем каждую строку только один раз. Это позволяет избежать проблемы, описанной выше, когда мы повторяем Джона миллион раз. (Посмотрите здесь , чтобы увидеть забавный способ увидеть это XD)

Самым большим преимуществом является проверка того, что мы не прошли через все. Никто больше не может использовать строки !!!

Кроме того, нам нужно только выделить буфер символов ОДИН РАЗ для хранения всей этой совокупной информации о конкатенации строк.

У нас также есть некоторая действительно хорошая информация для следующий парень, если мы хотим передать это, и заметить, что это почти что форма al go? Как здорово - это почти функция!

Теперь для финала! Вся эта тяжелая работа была проделана кем-то намного умнее нас обоих;)

printf("%s, %s, %s", arr[0].first_name, arr[0].last_name, arr[0].phone);

Думаю, я уже закончил редактирование !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...