简体   繁体   中英

Combining Strings into a List in C

Below is my code for the following issue. I'm trying to take a string of first names and string of last names that are separated by commas and transform them into a list of full names. For example, if firstnames = "John,Jane" and lastnames = "Smith,Doe" , then the output should be ["John Smith", "Jane Doe"] .

I believe my issue is arising in my use of strtok since first_names[i] = name is giving me an error. Any help on this would be much appreciated!

char **combine_names(char *firstnames, char *lastnames) {
    char first_names[50][50];
    char last_names[50][50];
    int i = 0;
    char *name = strtok(firstnames, ",");
    while (name != NULL) {
        first_names[i] = name;
        i++;
        name = strtok(NULL, ",");
    }
    i = 0;
    name = strtok(lastnames, ",");
    while (name != NULL) {
        last_names[i] = name;
        i++;
        name = strtok(NULL, ",");
    }
    char **names;
    names = malloc(strlen(first_names) * sizeof(char*));
    for (int i = 0; i < strlen(first_names); i++) {
        names[i] = malloc(51 * sizeof(char));
    }
    int i = 0;
    int j = 0;
    int k = 0;
    while (first_names[i] != '\0') {
        while (first_names[i][j] != '\0') {
            names[i][j] = first_names[i][j];
            j++;
        }
        names[i][j] = ' ';
        j++;
        while (second_names[i][k] != '\0') {
            names[i][j] = second_names[i][k];
            j++;
            k++;
        }
        names[i][j] = '\0';
        i++;
    }
    names[i] = '\0';
    return names;
}

The following line is causing an incompatible pointer error with the first argument. Why is that?

names = malloc(strlen(first_names) * sizeof(char*));

Using strtok() does indeed pose some problems, but the main issue is your allocating names with an invalid expression malloc(strlen(first_names) * sizeof(char*)); . first_names is not a C string, strlen(first_names) does not compute the number of entries in the first_names array.

Here is a simpler and safer approach:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **combine_names(const char *firstnames, const char *lastnames) {
    int n = 0;
    char **names = malloc(sizeof(*names) * (n + 1));
    char *p;

    if (names == NULL) {
        perror("cannot allocate memory\n");
    }

    while (*firstnames && *lastnames) {
        int len1 = strcspn(firstnames, ",");
        int len2 = strcspn(lastnames, ",");
        int size = len1 + 1 + len2 + 1;
        p = malloc(size);
        if (p == NULL) {
            perror("cannot allocate memory\n");
        }
        snprintf(p, size, "%.*s%s%.*s",
                 len1, firstnames,
                 len1 && len2 ? " " : "",
                 len2, lastnames);
        names = realloc(names, sizeof(*names) * (n + 2));
        if (names == NULL) {
            perror("cannot allocate memory\n");
        }
        names[n++] = p;
        firstnames += len1 + (firstnames[len1] == ',');
        lastnames += len2 + (lastnames[len2] == ',');
    }
    names[n] = NULL;
    return names;
}

Remember that first_names is a double array of characters. That means that first_names[i] is actually a string, or an array of characters. You can't assign directly to an array of characters, instead you have to write to the array character by character. The easiest way to do this is using string copy or strcpy(first_names[i], name) , but strcpy doesn't protect against buffer overflows. One method is to use strncpy , just be careful because this will not guarantee the string is null-terminated when the source string exceeds the size of the destination string. To fix this, use

strncpy(first_names[i], name, 50);
first_names[i][49] = '\0';

Considering the disadvantages of strncpy it's probably best to use a solution similar to @chqrlie.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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