I'm trying to replace ' ' (space) with '___' (triple underscore) in C.
Here is my code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
char *a = "12 34 56";
int a_l = strlen(a);
printf("str1: \"%s\" (%d)\n", a, a_l);
char *b = "___";
int b_l = strlen(b);
printf("str2: \"%s\" (%d)\n", b, b_l);
for (int i = 0; i < a_l; i++) {
if (a[i] == ' ') {
char *o = malloc(a_l + b_l);
strncpy(o, a, i);
strncpy(o + i, b, a_l);
//strncpy help
printf("out: \"%s\"\n", o);
}
}
return 0;
}
I think that it is right so far, but I need to replace the comment line with correct strncpy (take the rest of string a (excluding space) and append it to string o). So the output should be like this:
str1: "12 34 56" (8)
str2: "___" (3)
out: "12___34 56"
out: "12 34___56"
If there are other mistakes in my code, please tell me.
UPD: This shouldn't replace all spaces in a loop. If the source string contains 8 spaces, there should be 8 lines printed and in each line only one space should be replaced.
You are overcomplicating this so much that I just TL;DR.
Some remarks that you might surely want to read, learn, embrace well and use:
I. int is not for string lengths and stuff. size_t is for string lengths and stuff.
II. String literals cannot be modified, so using the legacy char * type for assigning them to a variable is no good by any means, const-qualify that poor pointer base type.
III. Use VLAs instead of malloc() if dynamic memory management is not really needed (we're not living in 1989 anymore).
IV. NUL-terminate your strings because C stdlib routines expect you to do so.
int main()
{
const char *in = "foo bar baz";
int nspc = 0;
for (const char *p = strchr(in, ' '); p; p = strchr(p + 1, ' '))
nspc++;
char buf[strlen(in) + nspc * 2 + 1];
memset(buf, 0, sizeof(buf));
const char *s = in;
for (const char *p = strchr(s, ' '); p; p = strchr(s, ' ')) {
strncat(buf, s, p - s);
strcat(buf, "___");
s = p + 1;
}
const char *end = in + strlen(in);
strncat(buf, s, end - s);
printf("%s\n", buf);
return 0;
}
You can try this one. The problem comes from the fact that a_l + b_l in your malloc is always the same value. It doesn't affect by number of spaces.
int count = 0, index = 0;
for (int i = 0; i < a_l; ++i) {
if (a[i] == ' ') {
count++;
}
}
const char *o = malloc(a_l + 2 * count + 1); // 2 is because you add 3 new symbols, but remove 1 so 3 - 1 = 2
memset(o, 0, sizeof(o));
for (int i = 0; i < a_l; ++i) {
if (a[i] != ' ')
o[index++] = a[i];
else {
o[index++] = '_';
o[index++] = '_';
o[index++] = '_';
}
}
Without using library function!!!
while(*string)
{
if(*string=='\\')
{
*string++;
while(repl_len--)
*dest++ = *repl_string++;
}
else
{
*dest++ = *string++;
}
repl_string = temp_repl_string;
repl_len = temp_repl_len;
}
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
size_t my_strlen(const char *str, size_t *spc){
size_t len;
*spc = len = 0;
while(*str){
++len;
if(*str++ == ' ')++*spc;
}
return len;
}
int main(void){
char *a = "12 34 56";
size_t spc;
int a_l = my_strlen(a, &spc);
printf("str1: \"%s\" (%d)\n", a, a_l);
char *b = "___";
int b_l = strlen(b);
printf("str2: \"%s\" (%d)\n", b, b_l);
char *p, *o = malloc(a_l - spc + spc * b_l + 1);
p=o;
for (int i = 0; i < a_l; i++) {
if(a[i] == ' ') {
strncpy(p, b, b_l);
p += b_l;
} else {
*p++ = a[i];
}
}
*p = '\0';
printf("out: \"%s\"\n", o);
free(o);
return 0;
}
I see that many answers have been added, but this may have been done very simply with a single loop. Since the string is very short, you can sacrifice memory over CPU and allocate an array 3 times +1 bigger than the original string, and be sure that it won't be overflowed:
const char* string= "12 34 56";
size_t length= strlen(string);
char result[length*3 +1];
unsigned int index= 0;
memset(result, '\0', length*3+1);
for(int i=0; i<length; i++)
{
if(string[i]!= ' ')
{
result[index++]= string[i];
}
else
{
strcat(result,"___");
index+= 3;
}
}
I found another thread and after reading the answers, I figured out that the right line should look like this:
strncpy(o + i + b_l, a + i + 1, a_l - i);
And after few fixes that were suggested in this thread my code looks like this:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
char *a = "12 34 56";
size_t a_l = strlen(a);
printf("str1: \"%s\" (%d)\n", a, a_l);
char *b = "___";
size_t b_l = strlen(b);
printf("str2: \"%s\" (%d)\n", b, b_l);
for (int i = 0; i < a_l; i++) {
if (a[i] == ' ') {
char *o = malloc(a_l + b_l);
strncpy(o, a, i);
strcpy(o + i, b);
strncpy(o + i + b_l, a + i + 1, a_l - i);
printf("out: \"%s\"\n", o);
free(o);
}
}
return 0;
}
And this prints the desired putput.
Related
I am not able to debug what is going on. The code seems correct yet I am new to pointers to pointers, and here there are 4 in series.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
return *(*(*(document + n - 1) + m - 1) + k - 1);
}
char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) {
return (*(*(document + m - 1) + k - 1));
}
char ***kth_paragraph(char ****document, int k) {
return *(document + k - 1);
}
char ****get_document(char *text) {
/* allocating memory */
int len = strlen(text);
/* allocate memory for each component first */
char ****document = malloc(sizeof(char ***));
char ***paragraph = malloc(sizeof(char **));
char **sentence = malloc(sizeof(char *));
char *word = malloc(sizeof(char) * 1024);
/* connect all the components to point in the sequence that is required */
*document = paragraph;
*paragraph = sentence;
*sentence = word;
/* declare some numbers as iterators for the words, sentences,etc. */
int parano = 0;
int sentno = 0;
int wordno = 0;
int charno = 0;
/* now iterate over the text filling and expanding the document at the same time */
/*----------------------------------------------------------------------------------------------------*/
/* feeding data in those spaces */
for (int i = 0; i < len; i++) {
if (text[i] == ' ') {
/* wrapping the current word, that is, resizing to len + 1 */
char *current_word = *(*(*(document + parano) + sentno) + wordno);
current_word = realloc(current_word, strlen(current_word) + 1);
/* resizing the current sentence to add another word*/
char **current_sentence = (*(*(document + parano) + sentno));
current_sentence = realloc(current_sentence, sizeof(char *) * (wordno + 2));
wordno++;
charno = 0;
/* allocating space to that new char * / word that has been created in the same sentence */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
}
else if (text[i] == '.') {
/* wrapping of the current word has to be done anyways */
char *current_word1 = *(*(*(document + parano) + sentno) + wordno);
current_word1 = realloc(current_word1, strlen(current_word1) + 1);
charno = 0;
if (text[i + 1] != '\n') {
/* the paragraph does not change, and the sentence ends */
/* resize that paragraph for adding another sentence */
char ***current_para = *(document + parano);
current_para = realloc(current_para, sizeof(char **) * (sentno + 2));
sentno++;
wordno = 0;
/* allocating word to that sentence */
*(*(document + parano) + sentno) = malloc(sizeof(char *));
/* allocating space for that word */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
} else {
/* if this is the last sentence of this paragraph*/
wordno = 0;
charno = 0;
sentno = 0;
}
}
else if (text[i] == '\n') {
/* paragraph has changed */
/* add another paragraph to the document */
document = realloc(document, sizeof(char ***) * (parano + 2));
parano++;
/* add sentence to that paragraph */
(*(document + parano) ) = malloc(sizeof(char **));
/* add a word to that paragrapgh */
(*(*(document + parano) + sentno)) = malloc(sizeof(char *));
/* allocate space for that word */
*(*(*(document + parano) + sentno) + wordno) = malloc(sizeof(char) * 1000);
} else {
scanf("%c", *(*(*(document + parano) + sentno) + wordno) + charno);
printf("%c\n", **(*(*(document + parano) + sentno) + wordno) + charno);
charno++;
}
}
return document;
}
char *get_input_text() {
int paragraph_count;
scanf("%d", ¶graph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char *returnDoc = (char *)malloc((strlen(doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
void print_word(char *word) {
printf("%s", word);
}
void print_sentence(char **sentence) {
int word_count;
scanf("%d", &word_count);
for (int i = 0; i < word_count; i++) {
printf("%s", sentence[i]);
if (i != word_count - 1)
printf(" ");
}
}
void print_paragraph(char ***paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(*(paragraph + i));
printf(".");
}
}
int main() {
char *text = get_input_text();
char ****document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3) {
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
char *word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
print_word(word);
}
else if (type == 2) {
int k, m;
scanf("%d %d", &k, &m);
char **sentence = kth_sentence_in_mth_paragraph(document, k, m);
print_sentence(sentence);
} else {
int k;
scanf("%d", &k);
char ***paragraph = kth_paragraph(document, k);
print_paragraph(paragraph);
}
printf("\n");
}
}
this is one of the questions on Hackerrank for the C language.
link to the question
hacker rank question
my profile
shows aborted, realloc invalid size. I couldn't find anything for the last 2 days.
inputs for the problem
2
Learning C is fun.
Learning pointers is more fun.It is good to have pointers.
3
1 2
2
5
6
2 1 1
4
3 1 1 1
expected output
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
When processing regular characters (final else clause) you read additional input instead of operating over text, i.e. instead of:
scanf("%c", &document[parano][sentno][wordno][charno]);
printf("%c\n", document[parano][sentno][wordno][charno]);
charno++;
you want to do:
document[parano][sentno][wordno][charno++] = text[i];
By the time we hit text[i] == ' ' for the first time the value of ***document is "3\n1 2\n2\n" but you wanted it to be "Learning".
(not fixed) When processing a word (`text[i] == ' ') you expand current word, yet, you hard-code 1000 when you allocate it initially so this doesn't make sense. Be consistent.
parano, sentno, wordno, charno is indices but same suggest they are counts. It's not wrong just confusing and why you have to wordno + 2 when relloc'ing.
Terminate words with `\0'.
When you process ' ' you add another word which you may or may not need which is fine. But when process a '.' you look ahead to the following letter is a \n or not. Be consistent. If you look ahead then you need to check that i + 1 < len, and it's fragile, say, there is a stray space before the \n.
(not fixed) Memory leaks. As the size of the sub-elements (paragraph, sentences and words) are private implementation details of get_document() you will have refactor the code to make those available. I suggest:
struct document {
char ****document;
size_t paragraphs;
size_t sentences;
size_t words;
}
(not fixed) Deduplicate. Similar to the print functions, create a allocation function per type.
(not fixed, really) get_input_text(). You split the into paragraphs then concatenate everything again into a local variable then copy it into a dynamically allocated variable:
char *str = malloc(BUFFER_LEN);
for(size_t i = 0, l = 0; l < lines && i + 1 < BUFFER_LEN; i += strlen(str + i)) {
int rv = fgets(str + i, BUFFER_LEN - i, stdin);
if(!rv) {
// handle error
break;
}
}
return s;
(not fixed) Separate i/o from processing. This simplifies testing and it makes it easier to figure out what is going on. In main(), you read a query type then 1 to 3 numbers. scanf()` tells you how many items where read so you simply do. As you don't use the kth_ functions for anything else just combine then with print_ funci
int n = scanf("%d %d %d %d", &type, &p, &s, &w);
switch(type) {
case 1:
if(n != 2) {
// handle error
}
print_paragraph(document, p);
break;
...
}
(not fixed) Add error checks for the remainingmalloc(), strdup() etc.
Don't hard-code magic values (1000). I introduced the constant WORD_LEN but you also have MAX_CHARACTERS which is kinda the same thing.
(not fixed) Consider using char *s = strpbrk(text + i, " .\n") to copy a word at a time. It will simplify \0 handling, and likely to be faster than walking the text a byte at a time, i.e. i += s - text + i, just handle the s == NULL special case.
valgrind is now happy other than leaks (see above):
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
#define WORD_LEN 1000
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int p, int s, int w) {
return document[p - 1][s - 1][w - 1];
}
char **kth_sentence_in_mth_paragraph(char ****document, int p, int s) {
return document[p - 1][s - 1];
}
char ***kth_paragraph(char ****document, int p) {
return document[p - 1];
}
char ****get_document(char* text) {
char ****document = malloc(sizeof ***document);
*document = malloc(sizeof **document);
**document = malloc(sizeof *document);
***document = malloc(WORD_LEN);
/* declare some numbers as iterators for the words, sentences,etc.*/
int parano = 0;
int sentno = 0;
int wordno = 0;
int charno = 0;
/* now iterate over the text filling and expanding the document at the same time*/
/*----------------------------------------------------------------------------------------------------*/
/* feading data in those spaces*/
size_t len = strlen(text);
for (size_t i = 0; i < len; i++) {
switch(text[i]) {
case ' ': {
document[parano][sentno][wordno][charno] = '\0';
wordno++;
char **words = realloc(
document[parano][sentno],
(wordno + 1) * sizeof *document[parano][sentno]
);
if(!words) {
printf("realloc of words failed\n");
exit(1);
}
document[parano][sentno] = words;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
case '.': {
document[parano][sentno][wordno][charno] = '\0';
sentno++;
char ***sentences = realloc(
document[parano],
(sentno + 1) * sizeof *document[parano]
);
if(!sentences) {
printf("realloc of sentences failed\n");
exit(1);
}
document[parano] = sentences;
document[parano][sentno] = malloc(sizeof **document);
wordno = 0;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
case '\n': {
document[parano][sentno][wordno][charno] = '\0';
parano++;
char ****paragraphs = realloc(
document,
(parano + 1) * sizeof *document
);
if(!paragraphs) {
printf("realloc of paragraphs failed\n");
exit(1);
}
document = paragraphs;
document[parano] = malloc(sizeof ***document);
sentno = 0;
document[parano][sentno] = malloc(sizeof **document);
wordno = 0;
document[parano][sentno][wordno] = malloc(WORD_LEN);
charno = 0;
break;
}
default: // character
document[parano][sentno][wordno][charno++] = text[i];
}
}
return document;
}
char *get_input_text() {
int paragraph_count;
scanf("%d", ¶graph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS];
char doc[MAX_CHARACTERS];
memset(doc, 0, sizeof doc);
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
return strdup(doc);
}
void print_word(char *word) {
printf("%s", word);
}
void print_sentence(char **sentence) {
int word_count;
scanf("%d", &word_count);
for(int i = 0; i < word_count; i++){
print_word(sentence[i]);
if(i + 1 != word_count)
printf(" ");
}
}
void print_paragraph(char ***paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(paragraph[i]);
printf(".");
}
}
int main() {
char *text = get_input_text();
char ****document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
switch(type) {
case 1: {
int p;
scanf("%d", &p);
print_paragraph(kth_paragraph(document, p));
break;
}
case 2: {
int p, s;
scanf("%d %d", &p, &s);
print_sentence(kth_sentence_in_mth_paragraph(document, p, s));
break;
}
case 3: {
int p, s, w;
scanf("%d %d %d", &p, &s, &w);
print_word(kth_word_in_mth_sentence_of_nth_paragraph(document, p, s, w));
break;
}
default:
printf("error\n");
}
printf("\n");
}
free(text);
}
Output as expected:
Learning pointers is more fun.It is good to have pointers.
Learning C is fun
Learning
Btw, a whole different way of solving this is problem is keep the original input (text) then write functions to directly extract a paragraph, sentence or word from that string. If you input is huge then create an index, say, (paragraph, sentence, word) to &text[i].
finally did it.
a big thanks to #allanwind for your support
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<assert.h>
#define MAX_CHARACTERS 1005
#define MAX_PARAGRAPHS 5
char *kth_word_in_mth_sentence_of_nth_paragraph(char ****document, int k, int m, int n) {
return *(*(*(document + n - 1) + m - 1) + k - 1);
}
char **kth_sentence_in_mth_paragraph(char ****document, int k, int m) {
return (*(*(document + m - 1) + k - 1));
}
char ***kth_paragraph(char ****document, int k) {
return *(document + k - 1);
}
char ****get_document(char *a)
{
int len = strlen(a);
char ****document = malloc(sizeof(char ***) * MAX_PARAGRAPHS);
int parano = 0;
char ***paragraph = malloc(sizeof(char **) * MAX_CHARACTERS);
int sentno = 0;
char **sentence = malloc(sizeof( char *) * MAX_CHARACTERS);
int wordno = 0;
char *word = malloc(sizeof(char ) * MAX_CHARACTERS);
int charno = 0;
for (int i = 0; i < len; i++)
{
/* after this way, try to learn switch conditionals*/
if (a[i] == ' ')
{
/* if find a space, that is there are more words within the same sentence*/
/* close the word*/
word[charno] = '\0';
/* add the word to the sentence*/
sentence[wordno] = word;
wordno++;
charno = 0;
/* create another word*/
char *tmp = malloc(sizeof(char) * MAX_CHARACTERS);
/* if the word got space without errors,*/
if (tmp != NULL)
{
word = tmp;
}
}
else if (a[i] == '.')
{
// terminate the word
word[charno] = '\0';
// add word to the sentence
sentence[wordno] = word;
wordno = 0;
charno = 0;
// add sentence to paragraph
paragraph[sentno] = sentence;
if (i != len - 1)
{
sentno++;
// allocate space for new sentence, as it is not the end
char **tmp1 = malloc(sizeof(char *) * MAX_CHARACTERS);
if (tmp1 != NULL)
{
sentence = tmp1;
}
// allocate space for new word
char *tmp2 = malloc(sizeof(char) * MAX_CHARACTERS);
if (tmp2 != NULL)
{
word = tmp2;
}
}
else
{
document[parano] = paragraph;
}
}
else if (a[i] == '\n')
{
// add paragraph to the document
document[parano] = paragraph;
parano++;
// allocate memory for another paragraph
char ***tmp3 = malloc(sizeof(char **) * MAX_CHARACTERS);
if (tmp3 != NULL)
{
paragraph = tmp3;
}
charno = 0;
wordno = 0;
sentno = 0;
}
else
{
/* step 1 read the text into the word char by char*/
word[charno] = a[i];
charno++;
}
}
return document;
}
char* get_input_text() {
int paragraph_count;
scanf("%d", ¶graph_count);
char p[MAX_PARAGRAPHS][MAX_CHARACTERS], doc[MAX_CHARACTERS];
memset(doc, 0, sizeof(doc));
getchar();
for (int i = 0; i < paragraph_count; i++) {
scanf("%[^\n]%*c", p[i]);
strcat(doc, p[i]);
if (i != paragraph_count - 1)
strcat(doc, "\n");
}
char* returnDoc = (char*)malloc((strlen (doc)+1) * (sizeof(char)));
strcpy(returnDoc, doc);
return returnDoc;
}
void print_word(char* word) {
printf("%s", word);
}
void print_sentence(char** sentence) {
int word_count;
scanf("%d", &word_count);
for(int i = 0; i < word_count; i++){
printf("%s", sentence[i]);
if( i != word_count - 1)
printf(" ");
}
}
void print_paragraph(char*** paragraph) {
int sentence_count;
scanf("%d", &sentence_count);
for (int i = 0; i < sentence_count; i++) {
print_sentence(*(paragraph + i));
printf(".");
}
}
int main()
{
char* text = get_input_text();
char**** document = get_document(text);
int q;
scanf("%d", &q);
while (q--) {
int type;
scanf("%d", &type);
if (type == 3){
int k, m, n;
scanf("%d %d %d", &k, &m, &n);
char* word = kth_word_in_mth_sentence_of_nth_paragraph(document, k, m, n);
print_word(word);
}
else if (type == 2){
int k, m;
scanf("%d %d", &k, &m);
char** sentence = kth_sentence_in_mth_paragraph(document, k, m);
print_sentence(sentence);
}
else{
int k;
scanf("%d", &k);
char*** paragraph = kth_paragraph(document, k);
print_paragraph(paragraph);
}
printf("\n");
}
}
I have structure
typedef struct StructString {
void **string;
ringinfo RingInfo; // now i dont use it
} StructString;
I use it
StructString str;
now I try to give my str.string value with random
int n = 1 + rand() % 30;
printf("%d\n", n);
str.string = RandomInput(str.string, n);
printf("%s\n", *(char **)str.string);
printf("%d\n", strlen(str.string));
the RandomInput func is here
void **RandomInput(void **s, const int n) {
int i;
s = malloc((n+1) * sizeof(void *));
for (i = 0; i < n; ++i) {
char c=rand()%128;
printf("%c ", c);
s[i]=&c;
printf("%d ", i);
printf("%c\n", *(char *)s[i]);
}
s[n]='\n';
return s;
}
and I have two problems:
sometimes there is "" char (use the screenshot)
str.string not what it should be (we can understand what it should be using the screenshot)
help me please, I don't understand
As the printable ascii characters are ranged between 0x20 (whitespace)
and 0x7e (tilda), you can randomly pick one with rand() % ('~' - ' ' + 1) + ' ' or rand() % 95 + 32.
If you do not have a specific reason, it will be better to define
the data type of string as char *, not void **. Otherwise
the assigned sequence of characters may have gaps between characters.
You need to terminate the string s with a null character instead of
a newline.
Then the rewrited code will look like:
#include <stdio.h>
#include <stdlib.h>
typedef struct StructString {
char *string;
// ringinfo RingInfo; // now i dont use it
} StructString;
char *RandomInput(char *s, const int n)
{
int i;
s = malloc((n + 1) * sizeof(char)); // strictly we should check the return value
for (i = 0; i < n; ++i) {
char c = rand() % ('~' - ' ' + 1) + ' ';
// pick a printable character between ' ' and '~'
printf("%c ", c);
s[i] = c;
printf("%d ", i);
printf("%c\n", s[i]);
}
s[n] = '\0';
return s;
}
int main()
{
StructString str;
int n = 1 + rand() % 30;
printf("%d\n", n);
str.string = RandomInput(str.string, n);
printf("%s\n", str.string);
printf("%d\n", strlen(str.string));
return 0;
}
It's an exercise where I have to build a function which returns a string called "secret identity" composed with your birth date, your name and your mother's name (for example, if "02/12/2007", "LUCY TOLKIEN" and "JENNIFER" it returns "20070212LT*J") but I'm struggling to concatenate the characters (like "L" and "T" of "LUCY TOLKIEN") to the string called "secret identity". I hope I could explain it well.
There's what I did by far:
int length(char * s) {
int i, n = 0;
for (i = 0; *(s + i) != '\0'; i++) {
n++;
}
return n;
}
void concatenate(char * s, char * t) {
int i = 0;
int j;
while (*(s+i) != '\0') {
i++;
}
for (j = 0; *(t+i) != '\0'; j++) {
*(s + i) = *(t + j);
i++;
}
*(s + i + 1) = '\0';
}
void copy(char * dest, char * orig) {
int i;
for (i = 0; *(orig + i) != '\0'; i++) {
*(dest + i) = *(orig + i);
}
*(dest + i) = '\0';
}
void geraIdentidade(void) {
char * ident;
int lname, ldate, lmom;
char name[80];
printf("Name: ");
scanf(" %[^\n]s", name);
lname = length(name);
char date[11];
printf("Date: ");
scanf(" %[^\n]s", date);
ldate = length(date);
char mom[20];
printf("Name (mom): ");
scanf(" %[^\n]s", mom);
lmom = length(mom);
char day[3], month[3], year[5];
int i, j, k;
for (i = 0; date[i] != '/'; i++) {
day[i] = date[i];
day[i + 1] = '\0';
}
for (j = 3, i = 0; date[j] != '/'; j++, i++) {
month[i] = date[j];
month[i + 1] = '\0';
}
for (k = 6, i = 0; k <= 9; k++, i++) {
year[i] = date[k];
year[i + 1] = '\0';
}
ident = (char*)malloc((lmom + ldate + lname) * sizeof(char)); //change lenght
if (ident != NULL) {
copy(ident, year);
concatenate(ident, month);
concatenate(ident, day);
}
else {
return NULL;
}
printf("%s\n", ident);
}
int main(void) {
geraIdentidade();
return 0;
}
For my opinion, 3 functions in your code:
int length(char * s)
void concatenate(char * s, char * t)
void copy(char * dest, char * orig)
You can make the code easier to do when you use some C standard functions in <string.h>:
size_t strlen(const char *s); // for length
char *strcpy(char *dest, const char *src); // for copy
char *strcat(char *dest, const char *src); // for concatenation
When you want to concatenate string and character, you just need to convert character to string by adding the \0 character to the character you want to concatenate. For example, if you want to concatenate T to string 20070212L:
#include <stdio.h>
#include <string.h>
int main()
{
char str[11] = "20070212L";
char ch[2] = "\0";
ch[0] = 'T';
strcat(str, ch);
printf("str = %s", str);
return 0;
}
The output:
str = 20070212LT
Let's suppose i have this phrase:
Hello $, Welcome!
I have to replace the '$' with a name, the result should be:
Hello Name, Welcome!
For now i did this, but it copies only the name and the first part of the phrase:
char * InsertName(char * string, char * name)
{
char temp;
for(int i = 0; i < strlen(string); i++)
{
if(string[i] == '$')
{
for(int k = i, j = 0; j < strlen(name); j++, k++)
{
temp = string[k+2];
string[k] = name[j];
string[k+1] = temp;
}
return string;
}
}
return "";
}
How can i shift all the elements after the name, so i can have the full string to be returned?
You can use sprintf() to print the output on a C-string, emulating the work done by printf():
Edit: You will have to include these two headers for this function to work:
#include <stdlib.h>
#include <memory.h>
An implementation of what you are trying to implement:
char* InsertAt(unsigned start, const char* source, const char* target, const char* with,
unsigned * position_ret)
{
const char * pointer = strstr(source, target);
if (pointer == NULL)
{
if (position_ret != NULL)
*position_ret = UINT_MAX;
return _strdup(source);
}
if (position_ret != NULL)
*position_ret = (unsigned)(pointer - source);
char* result = calloc(strlen(source) + strlen(with) + strlen(pointer), sizeof(char));
sprintf_s(result, strlen(source) + strlen(with) + strlen(pointer), "%.*s%.*s%.*s",
(signed)(pointer - source), _strdup(source),
(signed)strlen(with) + 1, _strdup(with),
(signed)(strlen(pointer) - strlen(target)), _strdup(pointer + strlen(target)));
return result;
}
Example:
#define InsertAtCharacter(src, ch, with) InsertAt(0u, (src), \
(char[]){ (char)(ch), '\0' }, (with), NULL)
int main(void)
{
printf("%s", InsertAtCharacter("Hello $, Welcome!", '$', "Name"));
return 0;
}
Try this !!!
#include <stdio.h>
#include <string.h>
char* replace(char* str, char* a, char* b)
{
int len = strlen(str);
int lena = strlen(a), lenb = strlen(b);
for (char* p = str; p = strstr(p, a); ++p) {
if (lena != lenb) // shift end as needed
memmove(p+lenb, p+lena,
len - (p - str) + lenb);
memcpy(p, b, lenb);
}
return str;
}
int main()
{
char str[80] = "Hello $,Welcome!";
printf("%s\n", replace(str, "$", "name"));
return 0;
}
It is sufficient to say that I am new to C so please have show some mercy ;).
I'm trying to compare two strings. The output shouldn't contain common characters. Sadly it does.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char msg[15] = "blueberry";
int c;
int s[15];
int j = 0;
int i = 0;
int k= 0;
int ok = 0;
int t = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
for (t=j=0; t < 15; ++t)
{
ok = 1;
//printf ("%c", s[t]);
}
for (k=0; msg[k] != '\0'; ++k)
{
if (s[t] == msg[k])
{
ok = 0;
}
}
if (ok == 1)
{
s[j] = s[t];
j++;
}
s[j] = '\0';
for (j = 0; j < 15; ++j)
printf ("%c ", s[j]);
}
The input from the keyboard is blackberry, expected output should've been U but sadly it is not. Any help please. Also why is it entering the nested for loop irrespective of condition?
My big thanks to everyone, it helped me a lot. I've figured out a way & am ok with the output. I've borrowed some ideas from A4L :).
To compare two string, you can use strcmp().
The following is a string compare program that you can use for your reference. I has both array and pointer version for better understanding.
#include <stdio.h>
int strcmp1(char a[], char b[])
{
int i=0;
while (a[i] == b[i]) {
if (a[i] == '\0')
return 0;
i++;
}
return a[i]-b[i];
}
int strcmp2(char *a, char *b)
{
while (*a == *b) {
if (*a == '\0')
return 0;
a++; b++;
}
return *a-*b;
}
int main()
{
char s1[] = "test string1";
char s2[] = "test string";
char s3[] = "aaa";
char s4[] = "bbb";
printf("strcmp1(%s, %s) = %d \n", s1, s2, strcmp1(s1, s2));
printf("strcmp2(%s, %s) = %d \n", s3, s4, strcmp2(s3, s4));
return 0;
}
given that msg contains "blueberry" and s contains "blackberry" this should do it
for (int i=0; i < strlen(msg); i++) {
for (int j = 0; j < strlen(s); j++) {
if (msg[i] != s[j]) {
printf ("%c", msg[i]);
}
}
}
yes it's ugly (using the strlen in the for gives me the chills, but I'm still low on coffeine today ^^)
i guess you want to find the first letter where the input differs from message
here is your own code with some fixes
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c;
char s[15];
int i = 0;
int k= 0;
int ok = 0;
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = (char) c;
++i;
}
// make sure to terminate the string after hitting enter
s[i] = '\0';
printf("input: %s\n", s);
printf("messg: %s\n", msg);
// run through both input and message with one counter
for (k=0; ok == 0 && msg[k] != '\0' && s[k] != '\0'; )
{
// if different chars stop
if (s[k] != msg[k]){
ok = 1;
} else {
// next char
k++;
}
}
if (ok == 1)
{
printf ("diff # index %d -> %c\n", k, msg[k]);
}
else
{
printf ("no diff\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
//Length to match
int comm(char* s1, char* s2){
int len = 0;
while(*s1 && *s2 && *s1++ == *s2++)
++len;
return len;
}
//commdiffcomm
/*
int commr(char* s1, char* s2){
int len = 0, limit;
int len1,len2;
len1 = strlen(s1);
len2 = strlen(s2);
limit = len1 > len2 ? len2 : len1;
s1 = s1 + len1;
s2 = s2 + len2;
while(limit-- && *--s1 == *--s2)
++len;
return len;
}
//bad
int diff(char* s1, char* s2, int* len1, int* len2){
int len, lenr, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
lenr = commr(s1, s2);
*len1 = strlen(s1) - len - lenr;
*len2 = strlen(s2) - len - lenr;
return len;
}
*/
int diff(char* s1, char* s2, int* len1, int* len2){
int len, s1_len, s2_len, wk_max, i, j;
len = comm(s1, s2);
if(strcmp(s1, s2)==0){
*len1 = *len2 = 0;
return len;
}
s1_len = strlen(s1 + len + 1);
s2_len = strlen(s2 + len);
wk_max = 0;
for(i = 1; i < s1_len ; i++){
for(j = 0; j < s2_len; j++){
int com_len;
com_len = comm(s1 + len + i, s2 + len + j);
if(wk_max < com_len){
wk_max = com_len;
*len1 = i;
*len2 = j;
}
}
}
return len;
}
int main(){
char str1[16] = "blueberry";
char str2[16] = "blackberry";
char dif1[16] = "";
char dif2[16] = "";
int len0;//length of top to diff pos
int len1;
int len2;
len0 = diff(str1, str2, &len1, &len2);
strncpy(dif1, str1 + len0, len1);
strncpy(dif2, str2 + len0, len2);
if(len1 !=0 && len2 != 0){
printf("%s different %s at position %d length %d (\"%s\")\n", str1, str2, len0, len1, dif1);
printf("%s different %s at position %d length %d (\"%s\")\n", str2, str1, len0, len2, dif2);
} else {
printf("two string is same.");
}
return 0;
}
/*
blueberry different blackberry at position 2 length 2 ("ue")
blackberry different blueberry at position 2 length 3 ("ack")
*/
There are a few problems with the code as is:
You don't null-terminate your input string. Attempting to use it with c string functons would spell trouble. To fix that, change
while (i < 15 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
to
while (i < 14 && (c = getchar()) != '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
Your specification is unclear as to whether you want your program to print the letters unique to msg, or to both s and msg. (i.e, do you want msg-s or (msg ∪ s)-(msg ∩ s) Assuming the first, the important part of your program goes like this:
k=0;
for(i=0;i<strlen(msg);i++){
int exists = 0;
for(j=0;!exists && j<strlen(s);j++){
if(msg[j] == s[i])
exists = 1;
}
if(!exists)
msg[k++] = msg[i];
}
s[k] = '\0';
The inner loop checks if s contains the current character in msg. If it does, we don't do anything, but if it doesn't, we append it to the end of a sublist we're creating on top of the bits of msg we've already processed.
your code is a mess even after the rewrite - there are too many errors to describe in detail
/*
blackbery
b l u e b e r r y
. . a c k b e . .
result = non-equal
*/
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char msg[15] = "blueberry";
int c, s[15], i,j,k, ok;
for (i=0; i < 15; i++) s[i] = 0;
for (i=0; i < 15 && (c = getchar()) != '\n'; i++) s[i] = c;
for (ok=1, k=0; msg[k] != '\0'; ++k)
if (s[k] != msg[k]) ok = 0; else s[k] = '.';
for (j = 0; j < 15; ++j) printf ("%c ", msg[j]);
printf("\n");
for (j = 0; j < 15; ++j) printf ("%c ", s[j]);
printf("\nresult = %s\n", ok ? "equal" : "non-equal");
}