Well, since the third attempt with the task decided, we start from the very beginning.
The first. You make a typical mistake: instead of focusing on solving individual problems , you begin to sculpt a pile of code that does everything at once , starting with no one needs (at this stage) data entry. It only interferes and confuses. Let's try to somehow organize the process.
Subtask 1: double certain characters in a line. We write a stub template, trying to understand what is at the input and what is at the output, and work only with it:
#include <stdlib.h> #include <string.h> #include <stdio.h> static char * dup_chars( const char * src, char ch ) { // пока тут пусто return NULL; } int main() { char * result = dup_chars( "abcabcabc", 'a' ); printf( "%s\n", result ); // уже понятно, что результирующая строка будет длинней, // и память для неё будет выделяться внутри dup_chars(), // поэтому освобождаем: free( result ); return 0; // C++ пока тут и не пахнет }
Anything more we do not need . With this template we start thinking further.
static char * dup_chars( const char * src, char ch ) { // определяем длину исходной строки: size_t src_len = strlen( src ); // понятно, что нам нужна будет как минимум длина исходной строки size_t desr_len = src_len; char * dest = malloc( dest_len + 1 ); return dest; }
We think further:
static char * dup_chars( const char * src, char ch ) { size_t src_len = strlen( src ); size_t dest_len = src_len; // считаем символы, которые удваиваются: for( size_t i = 0; i < src_len; i++ ) { if( src[i] == ch ) dest_len++; } // вот теперь мы точно знаем длину новой строки char * dest = malloc( dest_len + 1 ); return dest; }
And the last step, the doubling itself in the already prepared line:
static char * dup_chars( const char * src, char ch ) { size_t src_len = strlen( src ); size_t dest_len = src_len; for( size_t i = 0; i < src_len; i++ ) { if( src[i] == ch ) dest_len++; } char * dest = malloc( dest_len + 1 ); // будем использовать эту переменную как текущий индекс в строке-результате: dest_len = 0; for( size_t i = 0; i < src_len; i++ ) { // копируем символ исходной строки dest[dest_len] = src[i]; dest_len++; // он "наш"? копируем ещё раз: if( src[i] == ch ) { dest[dest_len] = ch; dest_len++; } } // и не забываем последний 0: dest[dest_len] = 0; return dest; }
Everything!
Now, in exactly the same way, breaking into pieces , try to solve the following problem: selection of substrings from one source string by a separator character. And when this is done, it will be possible to combine the solutions, turn on the input of external data, etc., etc., etc. ... Even - to be engaged in optimization :) But only after all the subtasks are solved, debugged and tested separately!
We continue . So far I still do not understand what it means "line by line" (and above that, square?). But we will try to get close to this, based on your code. Suppose some villain has forbidden to use dynamic memory allocation. This means that the dup_chars() function should take the input for the result and the size of this place. OK:
static char * dup_chars( const char * src, char * dest, size_t dest_len, char ch ) { size_t dest_pos = 0; size_t src_pos = 0; while( dest_pos < dest_len && src[src_pos] ) { dest[dest_pos] = src[src_pos]; dest_pos++; if( dest_pos >= dest_len ) { // Не хватило места! Хорошо бы вывести ошибку и/или вернуть, // NULL. А лучше - сначала подсчитать сколько понадобится // и если больше, чем dest_len, то вообще не портить // строку результата. Но пока в это не будем упираться. break; } if( src[src_pos] == ch ) { dest[dest_pos] = ch; dest_pos++; } src_pos++; } dest[dest_pos] = 0; return dest; }
Checking:
int main() { char src[] = "abcabcabc"; char dest[32]; printf( "%s\n", dup_chars( src, dest, sizeof(dest), 'a' ) ); return 0; }
It feels good. Now ( and only now, not earlier ), we switch to the second task: split the input string into substrings and pass them to the dup_chars() function. With standard C tools, this is done like this (for example, the separator will have a 0 character):
int main() { char src[] = "abc0abc0abc"; char dest[32]; char * ptr = strtok( src, "0" ); while( ptr ) { // тут у нас в ptr находится готовая C-строка, // если нужно где-то её сохранить, то самое время // это сделать printf( "%s\n", dup_chars( ptr, dest, sizeof(dest), 'a' ) ); ptr = strtok( NULL, "0" ); } return 0; }
But again some kind of radish came and forbade us to use the functions of the standard library. Or we do not want to modify the input string (what the strtok() function does; see its description in the reference library for the standard C library). So, we need to pass to dup_chars() not a "normal" C-string, but a pointer to the first character of the desired substring and its length. OK, we change a little bit:
static char * dup_chars( const char * src, size_t src_len, char * dest, size_t dest_len, char ch ) { size_t dest_pos = 0; size_t src_pos = 0; while( dest_pos < dest_len && src_pos < src_len ) { dest[dest_pos] = src[src_pos]; dest_pos++; if( dest_pos >= dest_len ) break; if( src[src_pos] == ch ) { dest[dest_pos] = ch; dest_pos++; } src_pos++; } dest[dest_pos] = 0; return dest; }
Now we are looking for separator characters in the input string and pass the fragments found to dup_chars() . And we will move the characters (the separator of substrings and that to double) in separate variables. And to make it “quite similar” (well, all of a sudden it’s not noticeable), let's call all the variables the same way as yours (although it’s wrong to give such names):
int main() { char text[] = "abc0abc0abc"; char stroka[32]; char sym = 'a'; char sym2 = '0'; char * ptr = text; char * end = strchr( ptr, sym2 ); while( end ) { printf( "%s\n", dup_chars( ptr, end-ptr, stroka, sizeof(stroka), sym ) ); // пропускаем все разделители, ведь их // может быть больше одного подряд: while( *end == sym2 ) end++; ptr = end; end = strchr( ptr, sym2 ); } // и захватываем "хвостик" входной строки, если он остался: if( *ptr ) printf( "%s\n", dup_chars( ptr, strlen(ptr), stroka, sizeof(stroka), sym ) ); return 0; }
Well, almost everything. I didn’t understand what it means "line by line", but it seems that the options will develop events we have already accumulated enough.
So now you can do other things: entering a separator character, entering a character for doubling, entering the original string, error handling (remember about exceeding the result length?), Accumulating the substrings of the original string and the result lines in arrays (for this we collected enough, which way more like it, so you can go) , optimization and other routine.
And the last part . Now we want to save both the substrings of the input string and the double string. For this we need two arrays of strings. Since we do not want C ++, we will have to allocate memory for them manually. How many? We do not know how many lines will be obtained as a result, and how long each of them will be. But it does not matter. To begin with, let us once again forget about this idiotic approach: solve all problems at once ! Let's try to calculate how many lines there will be, using one of the approaches described above (this one, in order not to spoil the input string, will still be useful to us):
int main() { char text[] = "abc0abc0abc"; char sym2 = '0'; size_t data_len = 0; char * ptr = text; char * end = strchr( ptr, sym2 ); while( end ) { data_len++; while( *end == sym2 ) end++; ptr = end; end = strchr( ptr, sym2 ); } if( *ptr ) data_len++; printf( "%u\n", data_len ); return 0; }
It turned out to bring 3 ? Fine! So you can allocate memory:
int main() { char text[] = "abc0abc0abc"; char sym2 = '0'; size_t data_len = 0; char ** strings_in; char ** strings_out; char * ptr = text; char * end = strchr( ptr, sym2 ); while( end ) { data_len++; while( *end == sym2 ) end++; ptr = end; end = strchr( ptr, sym2 ); } if( *ptr ) data_len++; strings_in = calloc( data_len, sizeof(char *) ); // на выходе столько же строк, сколько на входе: strings_out = calloc( data_len, sizeof(char *) ); // и подчищаем за собой: for( size_t i = 0; i < data_len; i++ ) { free( strings_in[i] ); free( strings_out[i] ); } free( strings_in ); free( strings_out ); return 0; }
Why did I write a seemingly meaningless dummy that does nothing? Then, it is necessary to assemble it, and drive it away to make sure that we have already distributed the memory correctly, freed it correctly, nowhere do we “flow” anything, the memory does not get stuck, etc. Ideally, this code (like any other, by the way) should be run through valgrind or through its analogs under Windows .
Now you need to insert the strings_in and strngs_out data into this template. And again we will not solve both problems at the same time ! First, fill in the input array only:
int main() { size_t i; char text[] = "abc0abc0abc"; char sym2[2] = { '0', 0 }; size_t data_len = 0; char ** strings_in; char * ptr = text; // обратите внимание: здесь мы уже скомбинируем // оба варианта прохода по строке, поэтому и чуть // изменили представление sym2. char * end = strchr( ptr, sym2[0] ); while( end ) { data_len++; while( *end == sym2[0] ) end++; ptr = end; end = strchr( ptr, sym2[0] ); } if( *ptr ) data_len++; strings_in = calloc( data_len, sizeof(char *) ); // делаем второй проход и копируем строки // в i - текущий индекс strings_in i = 0; ptr = strtok( text, sym2 ); while( ptr ) { strings_in[i] = strdup( ptr ); i++; ptr = strtok( NULL, sym2 ); } // выводим строки и сразу освобождаем память: for( i = 0; i < data_len; i++ ) { if( strings_in[i] ) { printf( "%s\n", strings_in[i] ); free( strings_in[i] ); } } free( strings_in ); return 0; }
It turned out to output exactly those lines that you expected? OK, then the next step is strings_out result to strings_out . This is where the very first version comes in handy, with dynamic memory allocation for it! We return to the very beginning, look at the prototype of the very first variant of dup_chars() and write the final version :
int main() { size_t i; char text[] = "abc0abc0abc"; char sym2[2] = { '0', 0 }; char sym = 'a'; size_t data_len = 0; char ** strings_in; char ** strings_out; char * ptr = text; char * end = strchr( ptr, sym2[0] ); while( end ) { data_len++; while( *end == sym2[0] ) end++; ptr = end; end = strchr( ptr, sym2[0] ); } if( *ptr ) data_len++; strings_in = calloc( data_len, sizeof(char *) ); strings_out = calloc( data_len, sizeof(char *) ); i = 0; // не хотите strtok()? не беда, чуть-чуть измените это // место (как? подумав головой!) ptr = strtok( text, sym2 ); while( ptr ) { strings_in[i] = strdup( ptr ); i++; ptr = strtok( NULL, sym2 ); } for( i = 0; i < data_len; i++ ) { strings_out[i] = dup_chars( strings_in[i], sym ); } for( i = 0; i < data_len; i++ ) { if( strings_in[i] ) { printf( "Source: %s\n", strings_in[i] ); printf( "Result: %s\n", strings_out[i] ); free( strings_in[i] ); free( strings_out[i] ); } } free( strings_in ); free( strings_out ); return 0; }
std::string. Your code should be something like this:string result; for (char c : source) { ... result += c; ... }string result; for (char c : source) { ... result += c; ... }string result; for (char c : source) { ... result += c; ... }. No need to try to change the line in the same place, just make a new one. - VladDstd::stringis not "other", but standard , I mean the native library for C ++. Especially since you usecoutandcin, so this is the same thing. - user6550 4:34 pmstd::string. Real, correct, the only existing in the language. What you use as a string (char*) is a C string. They are different. - VladD