简体   繁体   中英

C strcpy array of string pointers

I have an array declared like so:

char *array[4];

which is populated by a different function with strings, ie ["one", "two", "three", "four"].

My goal is to copy this array into a new array, excluding the last two elements, so new_array would contain ["one", "two"].

This is what I have tried so far:

int *new_array[2];

for (int i = 0; i < 2; i++){
    strncpy(new_array[i], array[i], strlen(array[i]));
}

But have received the following warning:

warning: passing argument 1 of ‘strncpy’ from incompatible pointer type [-Wincompatible-pointer-types]

note: expected ‘char * restrict’ but argument is of type ‘int *’

extern char *strncpy (char *__restrict __dest,

There are some problems with your code

First it declares an array of integer pointers (hence the warnings) then those pointers aren't initialized. strncpy isn't the proper function to call (and even if the memory was initialized, it wouldn't null-terminate your strings), you need strdup which does the proper allocation & copy:

char *new_array[2];

for (int i = 0; i < 2; i++){
    new_array[i] = strdup(array[i]);
}

(on some old systems, strdup may not be available. If you're in that case, just use new_array[i] = malloc(strlen(array[i]+1)); then strcpy(new_array[i],array[i]); )

Both methods allocate dynamic memory and need free when not used anymore.

But if you just want to store the pointers, for instance because array contains literals and you're not planning to modify your strings, you could just copy the pointer:

new_array[i] = array[i];

The source and destination are not compatible.
char *array[4]; int *new_array[2];

I hope you put int by mistake?

In addition to the wonderful answer given by Jean-François Fabre, I would point out that even a known size can change as a program evolves, for this reason it is useful to end lists with a known terminator (ie NULL or NaN).

I assume you're just beginning with C, but it's a good habit to get in to (the habit of seeking everything as transient and minimizing pre-conceptions in your code).

Although people point out that strdup isn't standard C, it is widely available. I will avoid it just for kicks. I hope you notice the error checks (excessive? maybe... but real code should be filled with these things).

Consider the following code (but don't use it, it might be slightly broken 😉):

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

char **string_array_dup(char *const *ary) {
  int count = 0;
  char **copy;
  if (!ary)
    return NULL;
  /* count string items - this is unsafe */
  while (ary[count++])
    ;
  if (!count)
      return NULL;
  /* allocate memory for array and set terminator. */
  copy = malloc(sizeof(*copy) * (count + 1));
  if (!copy)
    perror("ERROR"), exit(errno);
  copy[count - 1] = NULL;
  /* itterate over array, allocate and copy strings. */
  count = 0;
  while (ary[count]) {
    int register len = (int)strlen(ary[count]);
    copy[count] = malloc(len + 1); /* remember NUL byte */
    if (!ary[count])
      perror("ERROR"), exit(errno);
    memcpy(copy[count], ary[count], len + 1); /* copy NUL byte */
    count += 1;
  }
  return copy;
}

void string_array_print(char **ary) {
  int count = 0;
  while (ary[count]) {
    printf("%s ", ary[count++]);
  }
  printf("\n");
}

void string_array_free(char **ary) {
  int count = 0;
  /* free each string */
  while (ary[count]) {
    free(ary[count++]);
  }
  /* free container */
  free(ary);
}

int main(void) {
  char *array[] = {
      "String", "array", "is", "always", "terminated", "with", NULL,
  };
  char **copy = string_array_dup(array);
  if (!copy)
    perror("ERROR"), exit(errno);
  string_array_print(copy);
  string_array_free(copy);
  return 0;
}

By the way, this code could be optimized to use only a single malloc (or using realloc ) and a single free - at the cost of a more complicated copy process (and improving locality of the data and data access times).

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