2015-10-22 4 views
0

Я пишу простую функцию в C, которая должна построить массив символов из строки «abc» - поэтому он должен построить {'a', 'b', 'c'} - и верните указатель на этот массив. Вот мой код для этой функции:Создание массива char из строки (C)

char * makeArr() 
{ 
    static char arr[3]; 

    sprintf(arr, "%s\n", "abc"); 

    return arr; 
} 

Проблемы возникают, когда я называю этот метод в основной:

int main(int argc, char *argv[]) 
{ 
    char *arr[3]; 

    arr = makeArr(); 

    return 0; 
} 

Компилятор жалуется на кастинге/конфликтующих типов. Я уже давно играю с указателями, кастингом и разыгрыванием, но не могу заставить его работать. Пожалуйста, дайте мне знать, где моя логика неправильная.

+2

'char * arr [3]' - массив из трех символов 'char *'. 'makeArr' возвращает один' char * ', а не массив из трех. И incidientally, '' abc \ n "' имеет длину четыре символа, пять с нулевым терминатором, поэтому вы не должны пытаться записать его в буфер размера 3. – hobbs

+0

@hobbs Обновлен размер моего буфера, чтобы иметь более чем достаточно пространство. – freezefry

+0

Вы забыли точку с запятой после 'sprintf (arr,"% s \ n "," abc ")'. – MikeCAT

ответ

2

Хм ... есть несколько ошибки в этом коде. Давайте начнем с наиболее очевидным ваш компилятор жалуется:

char *arr[3]; 

Эта строка объявляет arr быть массивом из трех указателей к char. То, что вы возвращаете из своей функции, - это единственный указатель на char -> не соответствует.

Следующая:

static char arr[3]; 
sprintf(arr, "%s\n", "abc") 

Здесь Вы резерве 3 char с. sprintf() будет писать 5 char s.%s заменяется на 3 символа в вашем строчном литерале"abc". Вы добавляете символ новой строки, а затем добавляется 0 в качестве маркера конца «строки». Делает 5. Это btw равно undefined поведение. Вы пишете конец вашего массива. Код, подобный этому , может быть скомпилирован, но нет никакой гарантии о том, что произойдет во время выполнения.


делает сократить здесь. Вы должны прочитать о массивах и указателях на C. Если текст, который вы читаете, утверждает, что он тот же ... остановитесь прямо там и найдите лучший текст. Это не так.

Я попытаюсь объяснить это здесь кратко, поэтому он подходит для Q & A стиль.

Массив в C действительно является смежным пространством нескольких значений. char arr[3] означает переменную, которая содержит 3 char s.

С другой стороны, char * это просто указатель, указывающий на char - это может быть первым элементом массива.

В C вы не можете передавать массивы в качестве параметров функции, и вы не можете возвращать массивы из функции. Попытка сделать это приводит к неявному преобразованию: What is Фактически передано является указателем на первый элемент этого массива.

Я думаю, что последний бит информации, отсутствующей является то, что в C строковый литерал является: это массив (анонимный, например, он не имеет имени), содержащий все символы в двойных кавычках плюс a 0 прилагается. 0 обозначает конец «строки» в C.

В выражении строковый литерал оценивает указатель на первый элемент.

Так, что-то вроде этого:

char *foo = "bar"; 

приведет к foo указывая на b массива. Это как письмо

static const char no_name_0[] = { 'b', 'a', 'r', 0 }; 
char *foo = &(no_name_0[0]); 
2

Среди прочего, Вы смущены:

char arr[3]; // array of 3 chars.

и,

char *arr[3]; // array of 3 pointers to char.

В основной(), вы должны написать только char *arr;

1

Во-первых, char arr[3]; слишком snall для хранения "abc\n". Он должен содержать не менее 5 элементов, включая завершение нулевого символа.

Затем char *arr[3]; представляет собой 3-элементный массив char*.
Вы должны присвоить «возвращаемое значение s (она имеет char* тип) для arr[0] или другого элемента, или вы должны изменить тип arr в main функции char*, которая имеет тот же тип, как makeArr()» s makeArr() возвращаемого значения.

Кроме того, этот makeArr() не производит никакого массива и возвращает (указатель на) существующий массив. Yoy должен использовать malloc() для «создания массива».

UPDATE:

Присвоение значения char* в массив char arr[10]; кажется недействительным в C. Вы должны использовать strcpy() или strncpy() (безопаснее, чем strcpy()), чтобы скопировать строку, хранящуюся в массиве между массивами.

+0

Обновлен размер буфера до 10 – freezefry

0

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

void makeArr(char arr[]){ 
    sprintf(arr, "%s\n", "abc"); 
} 

Просто передать существующий объявленный массив функции makeArr ...

int main(int argc, char *argv[]) { 
    char arr[10]; 
    makeArr(arr); 
    return 0; 
} 
0

Вы не можете назначить результат makeArr в arr. Я предполагаю, что это ваша ошибка кастинга. Oversimifying, arr указывает на место в стеке, где выделяется массив из 10 символов. Итак, я бы прошел в arr, чтобы makeArr был символом char *.Итак, у вас получилось бы что-то вроде этого:

#include <stdio.h> 
char * makeArr(char *arr) 
{ 
    sprintf(arr, "%s\n", "abc"); 
    return arr; 
} 

int main(int argc, char *argv[]) 
{ 
    char arr[10]; 

    makeArr(arr); 
    printf("%s\n", arr); 
    return 0; 
} 
Смежные вопросы