Себастьян, если после ответа @ PaulOgilvie у вас все еще есть проблемы, то, скорее всего, из-за непонимания его ответа.Ваша проблема связана с тем, что buffer
выделено , но не инициализировано .Когда вы вызываете malloc
, он выделяет блок по крайней мере запрошенного размера и возвращает указатель на начальный адрес для нового блока - , но ничего не делает с содержимым нового блока -это означает, что блок является полными случайными значениями, которые только что оказались в диапазоне адресов для нового блока.
Поэтому, когда вы вызываете strcat(buffer, current_char_str);
в первый раз, и в buffer
и ничего, кроме случайного мусора, нетнет нуль-завершающий символ - вы вызываете неопределенное поведение .(в buffer
конца строки нет)
Чтобы исправить ошибку, вам просто нужно сделать buffer
пустой строкой после ее выделенияустановив первый символ в нуль-завершающий символ или используйте вместо него calloc
для выделения блока, который будет гарантировать, что все байты установлены в ноль.
Например:
int parse_path (const char *pathname)
{
int char_index = 0, ccs_index = 0;
char current_char = pathname[char_index];
char *buffer = NULL;
char *current_char_str = NULL;
if (!(buffer = malloc (2))) {
perror ("malloc-buffer");
return 0;
}
*buffer = 0; /* make buffer empty-string, or use calloc */
...
Также не используйте жесткие коды путей или чисел (включая 0
и 2
, но мы пока позволим им скользить).Жесткое кодирование "this/is/a/path/hello"
в parse_path()
make - довольно бесполезная функция.Вместо этого установите переменную pathname
в качестве параметра, чтобы я мог выбрать любой путь, который вы хотите отправить на него ...
Хотя сама идея realloc
одновременного использования 2-х символов неэффективнаВам всегда нужно realloc
с временным указателем, а не с самим указателем.Зачем?realloc
может и не получится, а когда это произойдет, он вернет NULL
.Если вы используете сам указатель, в случае сбоя вы перезапишете свой текущий адрес указателя на NULL
, потеряв адрес существующего блока памяти, что навсегда приведет к утечке памяти.Вместо этого
void *tmp = realloc (buffer, strlen(buffer) + 2);
if (!tmp) {
perror ("realloc-tmp");
goto alldone; /* use goto to break nested loops */
}
...
}
alldone:;
/* return something meaningful, your function is type 'int' */
}
Короткий пример, включающий исправления и временный указатель, будет выглядеть так:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int parse_path (const char *pathname)
{
int char_index = 0, ccs_index = 0;
char current_char = pathname[char_index];
char *buffer = NULL;
char *current_char_str = NULL;
if (!(buffer = malloc (2))) {
perror ("malloc-buffer");
return 0;
}
*buffer = 0; /* make buffer empty-string, or use calloc */
if (!(current_char_str = malloc (2))) {
perror ("malloc-current_char_str");
return 0;
}
while (current_char != '\0' && (int) current_char != 11) {
if (char_index == 0 && current_char == '/') {
char_index++;
current_char = pathname[char_index];
continue;
}
while (current_char != '/' && current_char != '\0') {
current_char_str[0] = current_char;
current_char_str[1] = '\0';
void *tmp = realloc (buffer, strlen(buffer) + 2);
if (!tmp) {
perror ("realloc-tmp");
goto alldone;
}
strcat(buffer, current_char_str);
char_index++;
current_char = pathname[char_index];
}
if (strlen(buffer)) {
printf("buffer(%s)\n", buffer);
current_char_str[0] = '\0';
buffer[0] = '\0';
}
if (current_char != '\0') {
char_index++;
current_char = pathname[char_index];
}
}
alldone:;
return ccs_index;
}
int main(int argc, char* argv[]) {
parse_path ("this/is/a/path/hello");
printf ("hello\n");
return 0;
}
( note: ваша логика довольно замучена выше, и вы могли быпросто используйте фиксированный буфер размером PATH_MAX
(включая limits.h
) и обходитесь без выделения. В противном случае вы должны выделить некоторое ожидаемое количество символов для buffer
для начала, например strlen (pathname)
, что обеспечит достаточно места для каждогоКомпонент пути без перераспределения. Я бы предпочел перераспределить на 1000 символов, чем испортить индексирование, опасаясь перераспределения 2 символов за раз ...)
Пример использования / Вывод
> bin\parsepath.exe
buffer(this)
buffer(is)
buffer(a)
buffer(path)
buffer(hello)
hello
Более прямой подход без выделения
Простое использование буфера размером PATH_MAX
или выделенного буфера размером не менее strlen (pathname)
позволитвам нужно просто переставить строку без перераспределения, например
#include <stdio.h>
#include <limits.h> /* for PATH_MAX - but VS doesn't provide it, so we check */
#ifndef PATH_MAX
#define PATH_MAX 2048
#endif
void parse_path (const char *pathname)
{
const char *p = pathname;
char buffer[PATH_MAX], *b = buffer;
while (*p) {
if (*p == '/') {
if (p != pathname) {
*b = 0;
printf ("buffer (%s)\n", buffer);
b = buffer;
}
}
else
*b++ = *p;
p++;
}
if (b != buffer) {
*b = 0;
printf ("buffer (%s)\n", buffer);
}
}
int main (int argc, char* argv[]) {
char *path = argc > 1 ? argv[1] : "this/is/a/path/hello";
parse_path (path);
printf ("hello\n");
return 0;
}
Пример использования / Вывод
> parsepath2.exe
buffer (this)
buffer (is)
buffer (a)
buffer (path)
buffer (hello)
hello
Или
> parsepath2.exe another/path/that/ends/in/a/filename
buffer (another)
buffer (path)
buffer (that)
buffer (ends)
buffer (in)
buffer (a)
buffer (filename)
hello
Теперь вы можете пройти любой путьВы хотели бы проанализировать как аргумент для вашей программы, и он будет проанализирован без необходимости что-либо менять или перекомпилировать.Посмотрите вещи и дайте мне знать, если у вас есть вопросы.