LINUX.ORG.RU

Создание строки в C (СИ)

 ,


1

3

Не могу найти внятного объяснения этого таинства.

Хочу создать пустую строку. Далее в коде в неё что-то записать (размер этого что-то неизвестен)

char *temp = NULL; //создаем указатель на будущую строку
int numofchars = 254; // 254 байта хватит всем


temp = (char*) malloc(numofchars+1); // выделяем память под нашу строку

strcpy(temp, "Privet, LOR");

...


free(temp);

Вопрос: правильно ли я всё делаю?

★★★★★

Последнее исправление: sniper21 (всего исправлений: 2)

Ответ на: комментарий от Jopich1

char *p = «String»;

Это используется если сразу известно что писать, а мне известно что писать только в процессе исполнения.

sniper21 ★★★★★
() автор топика

как то так...

char * strdup (const char *s) {
    char * d = malloc (strlen(s) + 1);   
    if (d == NULL) return NULL;          
    strcpy (d,s);                       
    return d;
}

vasyan
()
Ответ на: комментарий от anonymous

Ну это пока константа, тебе ведь может прийти еретическая идея принимать данные из вне...

itn ★★★
()
Ответ на: комментарий от sniper21

Если ты сделаешь man strcpy, то там сразу же увидишь ту функцию, которую надо использовать вместо strcpy.

redgremlin ★★★★★
()
Ответ на: комментарий от anonymous

Сегодня константа, завтра ты решил заюзать этот код для данных, приходящих по интернету, послезавтра хакеры украли твою кредитку и изнасиловали твоего кота. На си нельзя кодить неаккуратно.

redgremlin ★★★★★
()
Ответ на: комментарий от redgremlin

изнасиловать кота бесценно, для остального есть MasterCard ))

vasyan
()

Господа, так что с моим вопросом? :)

sniper21 ★★★★★
() автор топика
Ответ на: комментарий от sniper21

Это параноики, щас скажут что 11 пришло из интернета и надо проверить не больше ли 11 длины буфера, заставят проверить что вернул malloc, что malloc надо заменить на alloc, сalloc, что менеджер памяти С говно, указатели небезопасные и ты ходишь по краю пропасти.

ilovewindows ★★★★★
()
--для объявления строк Unbounded_String
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
--для использования операций ввода-вывода строк Unbounded_String
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO; 
 
 
procedure main is
	--Объявляем строку типа Unbounded_String
	S : Unbounded_String;
begin
	Put(To_Unbounded_String("Введите строку: "));
	Get_Line(S);
	Put_Line(S);
end main;

Ваш си убог!

anonymous
()
Ответ на: комментарий от sniper21

и получится:

strncpy(temp, «Privet, LOR», 11);

Тому, у кого это получится, надо солдатским ремнём по мягким местам пройтись.

redgremlin ★★★★★
()
strncpy(temp, source_string, numofchars);
temp[numofchars] = 0;

strncpy нужно передавать размер целевого буфера, чтобы тот не переполнить, а не исходного, который всё равно можно узнать при помощи strlen.

См. также: strlcpy, которая нестандартная, но не приводит к багам, когда strlen(source_string) == numofchars.

anonymous
()
Ответ на: комментарий от Gvidon

Да я уже взял, всё работает, но требуется вернуться к истокам...

sniper21 ★★★★★
() автор топика

Если известно, что длина строки небольшая, то зачем тут использовать malloc()? Можно и на стеке аллоцировать.

Sorcerer ★★★★★
()
Ответ на: комментарий от anonymous

Далее в коде в неё что-то записать (размер этого что-то неизвестен)

xmikex ★★★★
()
$ python3 -q
>>> temp=""
>>> temp
''
>>> //ляля тополя
  File "<stdin>", line 1
    //ляля топопля
     ^
SyntaxError: invalid syntax
>>> s="Privet, LOR"
>>> s
'Privet, LOR'
>>> PROFIT
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'PROFIT' is not defined
>>> 
anonymous
()

Вопрос: правильно ли я всё делаю?

Правильно. Но для надёжности можно сделать так:

temp = (char*) malloc(numofchars+1);
temp[numofshars]=0;
....
strncpy(temp, "Privet, LOR", numofchars);
Puzan ★★★★★
()
Ответ на: комментарий от Jopich1

Самая плохая функция, не пишет '\0' если нет места, зато пишет лишние '\0' если входная строка короче, проще скопипастить strlcpy из bsd если уж так хочется

anonymous
()
char* text;
size_t text_len;

text_len = sprintf(NULL, "%s, %s!", "Привет", "LOR");
text = malloc(text_len+1);
sprintf(text, "%s, %s!", "Привет", "LOR");

А вообще все неправильно, строки в сишке медленные используй

typedef struct {
    char* data;
    size_t length;
} string_t;

void
string_init/string_free/string_append/string_etcetcetc
/* а внутри этих функций memcpy, memcmp
   и советую нолик все же добавлять в конец, что бы можно было
   всегда твою строку использовать в обычных функциях./*

А если и так не хочешь, создавай какой нибудь буфер для работы со строками.

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 2)
Ответ на: комментарий от anonymous

Да можно тогда сразу

#include <duktape.h>

duk_eval(ctx, "'Hello,' + 'LOR' + '!'");
char* s = duk_get_string(ctx, -1);

linuhs_user
()
Ответ на: комментарий от Jopich1

Это неверный код, потому что вырашение слева имеет тип const char *. И совершенно другая семантика - константная строка известная на этапе компиляции vs. буффер для заполнения в runtime.

slovazap ★★★★★
()

Технически конкретно этот кусок кода (без ...) правильный. Но это плохая практика, поскольку в реальном мире кто-нибудь рано или поздно изменит строку на «Privet, linux.org.ru», не вникнув полностью в весь остальной код, а в буффер вдобавок попадут недовалидированные данные извне, и 254 байта «внезапно» не хватит.

slovazap ★★★★★
()
Ответ на: комментарий от linuhs_user

А вообще все неправильно, строки в сишке медленные используй

Пока мне достаточно если С строки будут быстрее std::string :)

sniper21 ★★★★★
() автор топика
Ответ на: комментарий от sniper21

Пока мне достаточно если С строки будут быстрее std::string :)

То, что ты демонстрируешь на С, будет быстрее работать даже на питоне. Не понимаешь, что в коде на С происходит, - не трогай С.

anonymous
()
Ответ на: комментарий от redgremlin

Ты ведь расскажешь, что ему помешает заюзать длину из интернета? И чем, в данном случае, ему поможет «та функция»? Ведь длинна берётся именно из интернета.

vcerloman
()
Ответ на: комментарий от sniper21

А с чего этой строке быть быстрее чем std::string?

anonymous
()
Ответ на: комментарий от anonymous

Ваш ада не достаточно бесстрашен

use std::io;

fn main() {
    let mut buffer = String::new();
    match io::stdin().read_line(&mut buffer) {
        Ok(n) => {
            println!("{} bytes read", n);
            println!("{}", buffer);
        }
        Err(error) => println!("error: {}", error),
    }
}

pftBest ★★★★
()
Ответ на: комментарий от sniper21

Cи быстрее не потому, что он Си, а потому, что перед тем как на нём писать - думают.

Возьмите нормальный язык и не морочьте людям голову.

RazrFalcon ★★★★★
()

Ты в курсе, что можешь создать строку на стеке, да?

anonymous
()
char *temp = NULL; //создаем указатель на будущую строку
size_t numofchars = 254; // 254 байта хватит всем


temp = (char*) malloc(numofchars+1); // выделяем память под нашу строку

// если строка не известна во время компиляции, то использовать
//size_t len_str = strlen(str);
//size_t len = len_str < numofchars ? len_str : numofchars;
size_t len = sizeof("Privet, LOR") < numofchars ? sizeof("Privet, LOR") : numofchars;
memcpy(temp, "Privet, LOR", len);
temp[len] = '\0';
...


free(temp);

Я раньше тоже strncpy использовал, но потом подумал что memcpy и strlen быстрее будет...

fsb4000 ★★★★★
()
Ответ на: комментарий от tyamur

Нельзя.

«lor» имеет тип const char*

warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
     p = "lor";
       ^

При нормальных флагах, типа Werror такой код даже не скомпилируется...

fsb4000 ★★★★★
()
Ответ на: комментарий от vcerloman

Ведь длинна берётся именно из интернета.

Вот когда поймёшь, почему «длиннннна» не берётся из интернеты, ты познаешь дзен strncopy.

redgremlin ★★★★★
()
Ответ на: комментарий от redgremlin

memcpy и strlen быстрее будет

Но оно же будет медленнее. И набирать многабукф дольше.

Охотно верю, видимо у вас максимальная длинна строки и средняя длинна строки близки...

fsb4000 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.