проблема с fputs и printf - PullRequest
       7

проблема с fputs и printf

0 голосов
/ 10 июля 2011

Я получил следующий код:

char* writeSpace(int i)
{
 fputs("                              " + (30-i), stdout);
}

printf("#%i key: %s%svalue: %s%s value2: %s", id, key, writeSpace(10), value, writeSpace(8), value2);

мой вывод должен выглядеть примерно так:

#1 key: foo          value: bar        value2: foobar

но это не так. это выглядит так:

                      #1 key: foo(null)value: bar(null)value2: foobar(null)

Что не так с моим кодом?

Ответы [ 5 ]

4 голосов
/ 10 июля 2011

Ну, вы fput выводите все эти пробелы на консоль, так что сначала вы получите их.

Тогда вы выводите все остальное, так что вы получите следующее.

Возможно, вы имели в виду от writeSpace до вернуть строку в стиле C, а не выводить ее на консоль.

Но будьте уверены, что вы выделите для этого место! Поскольку владение буферами памяти становится немного странным, лучше всего выделить пространство вне функции.

void writeSpace(char* buf, int i) {
   fputs("                              " + (30-i), buf);
}

char spaceBuf1[30];
writeSpace(spaceBuf1, 10);

char spaceBuf2[30];
writeSpace(spaceBuf2, 8);

printf("#%i key: %s%svalue: %s%s value2: %s",
   id, key, spaceBuf1, value, spaceBuf2, value2);

И рассмотрите возможность использования актуальных C ++ функций, таких как iostreams и std::string. Будет намного проще:

std::cout << "#" << id << " "
          << " key: " << std::setw(30) << key
          << " value: " << std::setw(30) << value
          << " value2: " << value2;

Я рекомендую эти ресурсы для изучения идиоматического C ++.

4 голосов
/ 10 июля 2011

Вы объявили writeSpace(), чтобы вернуть char*, но ничего из него не вернули.

0 голосов
/ 10 июля 2011

Остальные ответы имеют правильный ответ, который вы ищете.Однако я хотел бы попытаться добавить небольшое объяснение симптомов, которые вы видели, чтобы помочь вам избежать их в будущем.

при выполнении вашего оператора printf:

 printf("#%i key: %s%svalue: %s%s value2: %s", id, key, writeSpace(10), value, writeSpace(8), value2);

Два вызова метода writeSpace () выполняются до того, как сам printf что-либо сделает.Причина этого заключается в том, что возвращаемое значение этих методов используется в качестве аргументов для метода printf.Таким образом, последовательность выполнения для приведенной выше строки кода:

  • writeSpace (10), которая печатает пробелы в стандартном формате и возвращает нулевой указатель.
  • writeSpace (8)который выводит еще несколько пробелов в стандартный формат, а также возвращает нулевой указатель.
  • наконец, printf вызывается со следующими аргументами: printf ("#% i key:% s% svalue:% s% s value2:% s ", id, ключ, ноль , значение, ноль , значение2);

Вот почему вы видите пробелы, напечатанные в начале, но также почему вы видите, что «(null)» появляется в ваших выходных данных.

Таким образом, урок здесь заключается в том, что во время выполнения программы аргументы для метода разрешаются до вызова самого метода.

0 голосов
/ 10 июля 2011

Если вы хотите отформатировать переменную ws 'и вам абсолютно необходимо использовать обычный C, вы можете использовать строки такого формата (% * c, где * - это число ws, а c - символ, который нужно установить (в этом случае' '') конечно)):

sprintf(buffer, "%*cafterspace", 30, ' '); // Will print 30 ws and then "afterspace".<br> sprintf(buffer, "%*cafterspace", 15, ' '); // Will print 15 ws and then "afterspace".

Но вы все равно должны подготовить буфер, как объяснил Томалак!

0 голосов
/ 10 июля 2011

Ваша writeSpace функция не возвращает новую строку (даже если вы объявили ее таким образом), но пишет напрямую в терминал. Так как вы вызываете его как аргумент в вашем printf вызове, сначала вызывается writeSpace, печатает его содержимое, а затем printf печатает его содержимое. Вы должны сделать это так:

char* writeSpace(int i)
{
    char *ret = NULL;
    asprintf(ret, "                              " + (30-i));
    return ret;
}

Конечно, это требует от вас free памяти (в противном случае у вас будет утечка памяти). Вы можете сделать это так:

char *spaces = writeSpace(10);
printf("%s%i", spaces, 42);
free(spaces);

Альтернативой является использование статической переменной, которую сама функция очищает при следующем вызове:

char* writeSpace(int i)
{
    static char *ret = NULL;
    if (ret != NULL) free(ret);
    asprintf(ret, "                              " + (30-i));
    return ret;
}

Но это имеет тот недостаток, что вы можете использовать только один вызов writeSpace в ваших аргументах printf, так как второй очистит память предыдущего вызова. Все еще может быть то, что вы хотите.

Кстати, + (30-i) часть зла. То, что вы, вероятно, хотите, это вместо этого:

asprintf(ret, "%*s", i, ""); // Prints i spaces
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...