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
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");
}
}
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;
}
I would like to fit a string into multiple rows of a fixed width. I managed to separate the string into different rows so that their length will not pass the fixed width, but the problem is that some rows are not width (80) characters long, this is why I am trying to distribute the extra_space by adding spaces between words.
#include <stdio.h>
#include <string.h>
#include "stringdefault.h"
#include <conio.h>
#include <stdlib.h>
int main(){
int width = 80;
char s1[10000];
char substring[100] = " ";
char space = ' ';
gets(s1);
removeSpaces(s1);
char *base,*right_margin;
int extraSpace, numWords, numSpaces, incrementEachSpaceby, ind1, ind2, k;
int length;
length = string_length(s1);
base = s1;
for(int i = 0; i < width; i++)
{
printf("%d", i%10);
}
printf("\n");
while(*base)
{
if(length <= width)
{
puts(base); // display string
return(0); //and leave
}
right_margin = base+width;
while(!isspace(*right_margin))
{
right_margin--;
if( right_margin == base)
{
right_margin += width;
while(!isspace(*right_margin))
{
if( *right_margin == '\0')
break;
right_margin++;
}
}
}
*right_margin = '\0';
if(string_length(base) < width)
{
char *newStr = malloc(width);
extraSpace = width - string_length(base);
numWords = numberOfWords(base);
numSpaces = numWords - 1;
incrementEachSpaceby = extraSpace/numSpaces;
ind1 = 0;
ind2 = 0;
while (ind2 < width)
{
newStr[ind2] = base[ind1];
ind1++;
ind2++;
}
for(int i = 0; newStr[i]!='\0'; i++)
if((isspace(newStr[i])))
{
if(extraSpace > 0)
k = extraSpace;
else
k = 1;
while(k)
{
insert_substring(newStr, substring, i);
k--;
}
}
puts(newStr);
}
else
puts(base);
length -= right_margin-base+1; // +1 for the space
base = right_margin+1;
}
return 0;
}
stringdefault.h
int string_length(char s[])
{
int length = 0;
for(int i=0; s[i]!='\0'; i++)
length++;
return length;
}
char *substring(char *string, int position, int length)
{
char *pointer;
int c;
pointer = malloc(length+1);
if( pointer == NULL )
exit(EXIT_FAILURE);
for( c = 0 ; c < length ; c++ )
*(pointer+c) = *((string+position-1)+c);
*(pointer+c) = '\0';
return pointer;
}
void insert_substring(char *a, char *b, int position)
{
char *f, *e;
int length;
length = strlen(a);
f = substring(a, 1, position - 1 );
e = substring(a, position, length-position+1);
strcpy(a, "");
strcat(a, f);
free(f);
strcat(a, b);
strcat(a, e);
free(e);
}
char *removeSpaces(char *str)
{
int ip_ind = 0;
char *ptr;
while(*(str + ip_ind))
{
if ( (*(str + ip_ind) == *(str + ip_ind + 1)) && (*(str + ip_ind)==' ') )
{
ptr = str + ip_ind+1;
do{
*(ptr-1) = *ptr;
}while(*ptr++ != '\0');
}
else
ip_ind++;
}
*(str + ip_ind) = '\0';
return str;
}
The output that I get without the while loop inside the if statement
It seems that the newStr set of characters, contains spaces before it's first character.
I have problem with my alignement. This time I want my program to return words that ends and starts with the same letter. I've wrote something like this, but it seems to return random words.
#include <stdio.h>
#include <string.h>
void main()
{
char str[100];
int i, t, j, len;
printf("Enter a string : ");
scanf("%[^\n]s", str);
len = strlen(str);
str[len] = ' ';
for (t = 0, i = 0; i < strlen(str); i++)
{
if ((str[i] == ' ') && (str[i - 1] == str[0]))
{
for (j = t; j < i; j++)
printf("%c", str[j]);
t = i + 1;
printf("\n");
}
else
{
if (str[i] == ' ')
{
t = i + 1;
}
}
}
}
You can use strtok to split the strings from stdin, then apply a letter checker on each parsed word one at a time.
Something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAXCHAR 100
int is_start_end(char *word);
void exit_if_null(void *ptr, const char *msg);
int
main(void) {
char str[MAXCHAR];
char *word;
char **all_words;
int words_size = 1, word_count = 0;
int i, found;
all_words = malloc(words_size * sizeof(*all_words));
exit_if_null(all_words, "initial Allocation");
printf("Enter words(enter empty line to terminate):\n");
while (fgets(str, MAXCHAR, stdin) != NULL && strlen(str) != 1) {
word = strtok(str, " \n");
while (word !=NULL) {
if (words_size == word_count) {
words_size *= 2;
all_words = realloc(all_words, words_size * sizeof(*all_words));
exit_if_null(all_words, "Reallocation");
}
all_words[word_count] = malloc(strlen(word)+1);
exit_if_null(all_words[word_count], "Initial Allocation");
strcpy(all_words[word_count], word);
word_count++;
word = strtok(NULL, " \n");
}
}
printf("Words that have equal first and last letters:\n");
found = 0;
for (i = 0; i < word_count; i++) {
if (is_start_end(all_words[i])) {
found = 1;
printf("%s\n", all_words[i]);
}
free(all_words[i]);
all_words[i] = NULL;
}
if (found == 0) {
printf("None Found\n");
}
free(all_words);
all_words = NULL;
return 0;
}
int
is_start_end(char *word) {
int len;
len = strlen(word);
if ((len == 1) || (tolower(word[0]) == tolower(word[len-1]))) {
return 1;
}
return 0;
}
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
This line removes the null terminator of the string:
len = strlen(str);
str[len] = ' ';
thus the string no longer exists, what is left is just an ordinary array of characters.
The next call to strlen, in the body of the for loop, will cause undefined behavior.
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.