Почему от добавления printf зависит значение переменной? Или влияние printf на корректность работы программы
Задача: Создать функцию, которая разбивает строку символов на слова. Слова разделены пробелом. Функция возвращает массив указателей, каждый из которых ссылается на массив символов (слова). Слова должны заканчиваться нуль-терминатором.
Пример кода:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int count_words(char *str) //подсчет количества слов в заданной строке
{
int i;
int words;
i = 0;
words = 0;
while (str[i] != '\0')
{
if (str[i] == ' ')
words++;
i++;
}
words = words + 1;
return (words);
}
char **split_whitespaces(char *str)
{
int i;
int j;
int k;
int len; //длина слова
int w;
char **dest; //целевой массив
i = 0;
k = 0;
j = 0;
len = 0;
w = 0;
w = count_words(str);
dest = (char**)malloc(sizeof(char*) * w); //выделение памяти под массив указателей
while (str[i] != '\0')
{
while (str[i] != ' ' && str[i] != '\0') //определяем длину каждого слова
{
i++;
len++;
}
len++; //для добавления нуль-терминатора
//printf("len = %d\n", len); //волшебный printf
dest[k] = (char*)malloc(sizeof(char) * len); //выделение памяти под конкретное слово
dest[k][len - 1] = '\0';
len = 0;
k++;
i++;
}
i = 0;
k = 0;
while (i < w) //наполнение ранее созданных массивов
{
j = 0;
while (dest[i][j] != '\0')
{
dest[i][j] = str[k];
j++;
k++;
}
k++;
i++;
}
return (dest);
}
int main(int argc, char **argv)
{
char str[15] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', ' ', 'g', 'o', '\0'};
char **word;
word = split_whitespaces(str);
printf("%s\n%s\n%s", word[0], word[1], word[2]);
return (0);
}
Вопрос/проблема: Если не прописывать "волшебный printf", то длина каждого массива будет равна 2, не зависимо от длины слова. Если же прописать printf, то в итоге получим необходимый результат. В чем подвох? Почему так происходит? Какое влияние printf оказывает на значение переменной?
Ответы (2 шт):
У Вас тут слишком много ошибок, что бы разобраться, какая из них - самая главная.
Для начала - совет. Объявление массива символов:
char str[15] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', ' ', 'g', 'o', '\0'};
Полностью эквивалентно гораздо более простому и понятному:
char str[] = {"Hello, World go"};
Далее... Подозреваю, что записывая условие в операторе while таким образом:
while (str[i] != ' ' && str[i] != '\0')
Вы, не предполагали, что записали вот это:
while ((str[i] != (' ' && str[i])) != '\0')
Приоритет && выше приоритета операции сравнения !=
Ещё по поводу функции count_words. А что будет, если слова отделены друг от друга ДВУМЯ пробелами? А тремя? А знаком пунктуации?
Ещё бросилось в глаза:
dest[k][len - 1] = '\0';
Но вы только что делали len++ ?! Кстати говоря - совершенно напрасно. По выходу из цикла len УЖЕ указывает на разделитель слов.
Короче: убирайте ошибки одну за другой, а там уже будет видно....
Оказалось, проблема заключалось вот в чем:
dest[k] = (char*)malloc(sizeof(char) * len); //выделение памяти под конкретное слово
dest[k][len - 1] = '\0';
После выделения памяти таким образом нужно сразу заполнить его любыми символами, добавив:
dest[k] = (char*)malloc(sizeof(char) * len);
while (j < len)
{
dest[k][j] = ' ';
j++;
}
dest[k][len - 1] = '\0';
Теперь, при обращении к элементам массива dest для его наполнения, программа отрабатывает корректно.
А по-хорошему, переделать код так, чтобы массивы заполнялись сразу нужными значениями.
P.S. Почему добавление строки printf все исправляло, я так и не понял.