Как динамически выравнивать текст по центру в строке char *, чтобы вместить в общей сложности 16 пробелов в C?

Я пытаюсь выровнять строки по центру в общей сложности 16 пробелов, чтобы в конечном итоге напечатать их на ЖК-дисплее 16x2. Значения берутся из базы данных и помещаются в глобальную переменную, которая постоянно обновляется.

Значения в базе данных уже имеют строковый формат.

Что я хотел бы сделать, так это после получения значения из БД обновить глобальную переменную, чтобы она содержала строку с центром в 16 пробелах.

Я понимаю, что использование глобальных переменных может быть не лучшей практикой, но игнорирование этого есть ли способ сделать это?

char * systemInfoValues[5] = {" "," "," "," "," "}
for(int i=0; i< 5; i++){
     systemInfoValues[i] = PQgetvalue(res,i,0); //get the value from db;
     int len = strlen(systemInfoValues[i]);
     char tmp[20];

     sprintf(tmp,"%*s", (17-len)/2 + len, systemInfoValues[i]);
     strcpy(systemInfoValues[i],tmp);
}

0 = пробел ххххх = строка из БД

Если длина строки нечетная Я ожидаю, что вывод будет [00xxxxxxxxxxxxx0]

если длина строки четная Я ожидаю, что вывод будет [00xxxxxxxxxxxx00]

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
189
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете сделать это другим способом (без использования функции sprintf). Я не знаю ни о каком интерфейсе функции sprintf, который позволил бы вам это сделать, но вы можете решить проблему с помощью простого strcpy переменных.

Это основная программа, которая решит вашу проблему, она задокументирована сама по себе, поэтому вы должны понять, как применить это к своему коду:


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

/* This simple program would transfer the original string that is in the                                                                                                                       
 * out_value to be centralized in this variable. */                                                                                                                                            
int main(void) {                                                                                                                                                                               
    char out_value[17] = "1234567891";                                                                                                                                                         
    char temp[20] = {0};                                                                                                                                                                       
    int first_index = 0;                                                                                                                                                                       
    int string_length = 0;                                                                                                                                                                     

    /* Copy the string to the temp variable, to modify the chars in                                                                                                                            
     * out_value. */                                                                                                                                                                           
    strcpy(temp, out_value);                                                                                                                                                                   

    /* Find out the index for the first char to be placed in the centralized                                                                                                                   
     * string. */                                                                                                                                                                              
    string_length = strlen(temp);                                                                                                                                                              
    first_index = (16 - string_length) / 2;                                                                                                                                                    

    /* Set all the values of the out_value to be the wanted value of space (here                                                                                                               
     * it is 0 for visualizing, it can be space to not be present). */                                                                                                                         
    memset(out_value, '0', 16);                                                                                                                                                                

    /* Copy the original string back, moving the start of it, so it would be                                                                                                                   
     * centralized. */                                                                                                                                                                         
    strncpy(&(out_value[first_index]), temp, string_length);                                                                                                                                   

    /* Print the string. */                                                                                                                                                                    
    printf("%s", out_value);                                                                                                                                                                   
}         

При изменении вашего кода для работы с этим код будет выглядеть примерно так:

char * systemInfoValues[5] = {NULL}                                                                                                                                                            
for(int i=0; i< 5; i++){                                                                                                                                                                       
     systemInfoValues[i] = PQgetvalue(res,i,0); //get the value from db;                                                                                                                       
     int len = strlen(systemInfoValues[i]);                                                                                                                                                    
     char tmp[20];                                                                                                                                                                             
     int first_index = 0;                                                                                                                                                                      

     strcpy(tmp, systemInfoValues[i]);                                                                                                                                                         
     first_index = (16 - len) / 2;                                                                                                                                                             

     memset(systemInfoValues[i], ' ', 16);                                                                                                                                                               
     strncpy(&(systemInfoValues[i][first_index]), tmp, len);                                                                                                                                   
}     

Обратите внимание, что я изменил инициализацию значения systemInfoValues. Когда вы его инициализировали, вы помещаете туда пустые строки. Обратите внимание, что это плохая привычка. Помещение туда пустых строк (или строк с одним пробелом) выделит память для этой строки (которую вы никогда не будете использовать).

Вы не включили определение в функцию PQgetvalue, но предполагая, что она вернет указатель на char, это должно работать. Но этот код также изменит глобальное значение. Если вы не хотите его менять, вы не должны помещать туда результат, а копируете результат в строку, прежде чем вносить в нее какие-либо изменения. После изменения кода он должен выглядеть так:

char systemInfoValues[5][17] = {{0}}                                                                                                                                                           
for(int i=0; i< 5; i++){                                                                                                                                                                       
     char *global_reference = PQgetvalue(res,i,0); //get the value from db;                                                                                                                    
     int len = strlen(systemInfoValues[i]);                                                                                                                                                    
     char tmp[20];                                                                                                                                                                             
     int first_index = 0;                                                                                                                                                                      

     strcpy(tmp, global_reference);                                                                                                                                                            
     first_index = (16 - len) / 2;                                                                                                                                                             

     memset(systemInfoValues[i], ' ', 16);                                                                                                                                                               
     strncpy(&(systemInfoValues[i][first_index]), tmp, len);                                                                                                                                   
}        

редактировать: видимо есть интерфейс для работы функции sprintf (как вы изначально хотели). Чтобы увидеть это, обратитесь к ответу рыба-меч

Хорошо, я проверю это, как только вернусь за свой стол, и отправлю обновление.

mmajdalani 08.05.2019 20:54
Я не знаю ни одного интерфейса функции sprintf, который позволил бы... – да ;p
Swordfish 08.05.2019 21:14

Это работает, хотя я получаю случайные значения в конце строк. Вывод: 0xxxxxxxxxxxxx00, 000000xxxx0000008G, 00000xxxxxx00000PG

mmajdalani 08.05.2019 21:25

Я не могу это воспроизвести. Вы запускаете мою основную функцию или свой код? Кажется, что что-то работает над терминатором NULL в конце (это произойдет, если длина, которую вы указали, равна 16, а не 17, например).

Omri Sarig 08.05.2019 21:32

Позвольте мне попробовать еще раз с 17

mmajdalani 08.05.2019 21:38

17 усугубляет ситуацию, индекс 1 перезаписывает индексы 3,4,5 и добавляет случайные символы

mmajdalani 08.05.2019 21:43

В моем коде кажется, что строки, исходящие из PQGetValue, не действуют как обычные строки. Вот описание того, что возвращает PQGetvalue: «Для данных в текстовом формате значение, возвращаемое PQgetvalue, представляет собой строковое представление значения поля, заканчивающееся нулем».

mmajdalani 08.05.2019 21:51

Я думаю, вам следует изменить свой код, чтобы он работал как мой последний пример, поскольку проблема, похоже, связана с возвращаемым значением PQGetValue, а не с кодом централизации. Если вы можете воспроизвести проблему в основной функции, то она связана с кодом централизации, но если нет, то проблема больше связана с интерфейсом, который вы используете (и PQGetValue), и мне в настоящее время не хватает данные (из вашего вопроса), чтобы решить эту проблему.

Omri Sarig 08.05.2019 21:56
Ответ принят как подходящий

Это простая 6-строчная функция. симметрия дает вам возможность

char *centerinstring(char *buff, size_t len, const char *str, int symetry)
{
    size_t strl = strlen(str);
    size_t pos = (len - strl) / 2 + (strl & 1) * !!symetry;

    memset(buff,' ', len);
    buff[len] = 0;

    memmove(buff + pos, str, strl);
    return buff;
}

int main()
{
    char buff[11];

    printf("|%s|\n", centerinstring(buff, 10, "1234567", 1));
    printf("|%s|\n", centerinstring(buff, 10, "1234567", 0));

    return 0;
}

или с возможностью выделения памяти под бафф (если передать NULL

char *centerinstring(char *buff, size_t len, const char *str, int symetry)
{
    size_t strl = strlen(str);
    size_t pos = strl / 2 + (strl & 1) * !!symetry;

    buff = buff ? malloc(len + 1) : buff;

    if (buff)
    {
        memset(buff,' ', len);
        buff[len] = 0;

        memmove(buff + pos, str, strl);
    }
return buff;
}

Какой вариант симметрии?

mmajdalani 08.05.2019 21:28

если даже вы не можете иметь это одно дополнительное место справа или слева

0___________ 08.05.2019 21:30

Ладно, buff здесь — значение базы данных, а str — временная? или наоборот?

mmajdalani 08.05.2019 21:31

неважно

0___________ 08.05.2019 21:34

``` char tmp[20]; набор памяти (tmp, ' ', len); тмп[длина] = 0; memmove(tmp+pos,systemInfoValues[i],strl); strcpy(systemInfoValues[i],tmp); ``` Приводит к ошибке seg

mmajdalani 08.05.2019 21:37

использовать функцию как задано.

0___________ 08.05.2019 21:41

Функция работает с "1234567", но не с моими строками. Вот описание того, что возвращается из PQGetValue: «Для данных в текстовом формате значение, возвращаемое PQgetvalue, представляет собой строковое представление значения поля, заканчивающееся нулем».

mmajdalani 08.05.2019 21:48

sprintf()-комфорт:

#include <assert.h>
#include <string.h>
#include <stdio.h>

void center(char *dst, char *src, size_t width)
{
    assert(dst && src && width);

    size_t src_len = strlen(src);

    if (src_len >= width) {
        *dst = '\0';
        return;
    }

    int right = (int)(width - src_len) / 2;
    int left = right + (int)src_len;
    right -= (src_len & 1);

    sprintf(dst, "%*s%*s", left, src, right, "");
}

int main(void)
{
    char destination[17];

    center(destination, "12345678901234", sizeof(destination));
    printf("\"%s\"\n", destination);
}

Где я могу найти assert.h?

mmajdalani 08.05.2019 21:27

@mmajdalani Это должно быть частью стандартной библиотеки вашего компилятора?

Swordfish 08.05.2019 21:27

@mmajdalani, если нет, вы можете удалить assert() из функции. Просто убедитесь, что вы не передаете ему указатель NULL.

Swordfish 08.05.2019 22:54

Другие вопросы по теме