How to correct my C custom printf( ) code - c

I have a problem with the output of my custom printf code when I use 4 or more arguments, and I can't find out where is the problem
` #include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int _printf(const char *format, ...);
int main()
{
_printf("%c%cth %s%s a%cg%s: Y%sou %s no%ching%s Snow.%c", 'W', 'i', "some ", "more", 'r', "s", "", "know", 't', ", Jon", '\n');
}
/**
* _printf - Custum printf function
* #format: A string containing the caracters to print
* Return: the count of the printed charecters
*/
int _printf(const char *format, ...)
{
va_list args;
int count = 0;
int i, j, length = 0;
char c, *p, *ptr;
va_start(args, format);
if (format == NULL)
return (-1);
for (i = 0; format[i] != '\0'; i++)
{
if (format[i] == '%')
{
i++;
if (format[i] == 'c')
{
c = va_arg(args, int);
count += write(1, &c, 1);
}
if (format[i] == 's')
{
ptr = va_arg(args, char*);
if (ptr == NULL)
count += write(1, "(null)", 6);
else
{
while (*ptr != '\0')
{
length++;
ptr++;
}
p = malloc((length + 1) * sizeof(char));
for (j = 0; j < (length + 1); j++)
p[length - j] = *(ptr - j);
count += write(1, p, length);
free(p);
}
}
if (format[i] == '%')
count += write(1, &format[i], 1);
}
else
count += write(1, &format[i], 1);
}
va_end(args);
return (count);
} `
for example when I try to test my function in the main code like this:
_printf("%c%cth %s%s a%cg%s: Y%sou %s no%ching%s Snow.%c", 'W', 'i', "some ", "more", 'r', "s", "", "know", 't', ", Jon", '\n');
expected out put is :
With some more args: You know nothing, Jon Snow.
What I get :
With some more argonknows: Y Jonknowou .%c, Jonknow nothinging%s Snow.%c, Jon Snow.

At least these issues:
Incorrect length determination
while (*ptr != '\0') { length++; ptr++; } does not start with length = 0, except for the first time it is used.
Code sets the null character
for (j = 0; j < (length + 1); j++) p[length - j] = *(ptr - j); populates p[] with the null character. Not needed.
Allocation not needed
Instead:
if (format[i] == 's') {
const char *ptr = va_arg(args, char*);
if (ptr == NULL) {
ptr = "(null)";
}
size_t length;
for (length = 0; ptr[length]; length++) {
;
}
count += write(1, ptr, length);
}

Related

a program that reads simple data declarations and responds with the amount of memory that would be allocated to that variable

Each input line should consist of
- A type name, which must be one of the following: char, int, short, long, float, or double.
- One or more individual declaration specifications separated by commas.
- A semicolon marking the end of line.
The program should exit if it reads a blank input line.
I wrote the following code for this program. It seems to work well,except thefollowing warning I get :
d:\documents\documents\visual studio 2012\projects\project3\project3\source.c(108): warning C4715: 'theSizeOf' : not all control paths return a value.
By the way, I wonder if it can be improved (maby by using strtok?). I also would like to add a file in this program which is to contain the output and I am not sure at all how it has to be done.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void bytesPerValue(char str[]);
int theSizeOf(char *str);
int strToNumber(char *str);
void main()
{
char str[50];
gets(str);
bytesPerValue(str);
}
void bytesPerValue(char str[]) //Ex5
{
int i = 0, j = 0;
int temp = 1;
int size;
char* tempChar = (char*)malloc((strlen(str))*sizeof(tempChar));
while (!isspace(str[i]) || str[i]=='*') //checking the type of the variables
{
tempChar[j] = str[i];
i++;
j++;
}
tempChar[j] = '\0';
size = theSizeOf(tempChar);
j = 0;
i++;
while (str[i] != ';')
{
if (isalpha(str[i]) || str[i]=='_') // for normal variables and arrays
{
while (str[i] != ',' && str[i] != ';') //runs until ', ' or '; '
{
if (isspace(str[i]))
{
while (isspace(str[i]))
i++;
}
if (str[i] == '[') //checks if it is array
{
printf("%c", str[i]);
i++;
while (str[i] != ']')
{
tempChar[j] = str[i]; //copies the value in the string
i++;
j++;
}
tempChar[j] = '\0';
temp = strToNumber(tempChar); //converting to number so I can valuate the bytes
}
printf("%c", str[i]);
i++;
if (isspace(str[i]))
{
while (isspace(str[i]))
i++;
}
}
printf(" requires %d bytes \n", temp*size);
}
if (str[i] == '*') //for pointers
{
while (str[i] != ',' && str[i] != ';')
{
printf("%c", str[i]);
i++;
if (isspace(str[i]))
{
while (isspace(str[i]))
i++;
}
}
printf(" requires %d bytes \n", 4);
}
if (str[i] != ';')
i++;
}
}
int theSizeOf(char* str) // checking the size of the variable
{
if (strcmp(str, "int")==0 || strcmp(str, "long")==0 || strcmp(str, "float")==0)
return 4;
if (strcmp(str, "char")==0)
return 1;
if (strcmp(str, "double")==0)
return 8;
if (strcmp(str, "short")==0)
return 2;
}
int strToNumber(char* str) //converting the string to number
{
int temp=1;
int num=0;
int t;
int i;
int length = strlen(str);
for (i = length-1; i >= 0; i--)
{
t = str[i] - '0';
num += t * temp;
temp *= 10;
}
return num;
}
As Sourav Ghosh mentioned this is definetly post for Code Review.
But since you already wasted your time posting here, I would advise you read up this:
Please explain the output of sizeof()
I am not quite sure why you defined your own function when you could have used the sizeof operator which do exactly what your function is doing.
Edit:
Another good example
Edint 2.0 : The warning you got is the compiler basicly saying, "What will happen if neither of your cases are matched?" . In more simple words it asks for a else case in which to go in the scenario where none of the if's match the case.
Regarding how to write the value to a file, you can use fprintf();
FILE *f = fopen("file.txt", "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
int i = 1;
fprintf(f,"%d", i);
fclose(f);
More information and examples for fprintf
I have changed my code by using sizeof and I get a wrong output.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void bytesPerValue(char str[]);
int strToNumber(char *str);
void main()
{
char str[50];
gets(str);
bytesPerValue(str);
}
void bytesPerValue(char str[])
{
int i = 0, j = 0;
int temp = 1;
int size;
char* tempChar = (char*)malloc((strlen(str))*sizeof(tempChar));
while (str[i]!=' ' || str[i]=='*') //checking the type of the variables//
{
tempChar[j] = str[i];
i++;
j++;
}
tempChar[j] = '\0';
size = sizeof(tempChar);
j = 0;
i++;
while (str[i] != ';')
{
if (isalpha(str[i]) || str[i]=='_') // for variables and arrays//
{
while (str[i] != ',' && str[i] != ';') //runs until ', ' or '; ' //
{
if (str[i]==' ')
{
while (str[i]==' ')
i++;
}
if (str[i] == '[') //checks if it is array//
{
printf("%c", str[i]);
i++;
while (str[i] != ']')
{
tempChar[j] = str[i]; //copies the value in the string//
i++;
j++;
}
tempChar[j] = '\0';
temp = strToNumber(tempChar); //converting to number in order to valuate the bytes//
}
printf("%c", str[i]);
i++;
if (isspace(str[i]))
{
while (isspace(str[i]))
i++;
}
}
printf(" requires %d bytes \n", temp*size);
}
if (str[i] == '*') //for pointers//
{
while (str[i] != ',' && str[i] != ';')
{
printf("%c", str[i]);
i++;
if (str[i]==' ')
{
while (str[i]==' ')
i++;
}
}
printf(" requires %d bytes \n", 4);
}
if (str[i] != ';')
i++;
}
}
For example, for the following input: char c, *cprt, carray[80];
I get the following output:
c requires 4 bytes
*cprt requires 4 bytes
caaray[] requires 320 bytes
which is wrong...
I have just edited my code, not using sizeof. I also add a use of file in my code. I think it works well now. I would be happy if you may please tell me what you think about it, whether my code should be improved or fixed.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void bytesPerValue(char str[], char* filename) ;
int theSizeOf(char *str);
int strToNumber(char *str);
void main()
{
char str[50];
gets(str);
bytesPerValue(str,"input.txt");
}
void bytesPerValue(char str[], char* filename)
{
int i = 0, j = 0;
int temp = 1;
int size;
char* tempChar = (char*)malloc((strlen(str))*sizeof(tempChar));
FILE *f=fopen(filename,"w");
if (f==NULL)
exit(1);
while (str[i]!=' ' || str[i]=='*') //checking the type of the variables//
{
tempChar[j] = str[i];
i++;
j++;
}
tempChar[j] = '\0';
size = theSizeOf(tempChar);
j = 0;
i++;
while (str[i] != ';')
{
if (isalpha(str[i]) || str[i]=='_') // for variables and arrays//
{
while (str[i] != ',' && str[i] != ';') //runs until ', ' or '; ' //
{
if (str[i]==' ')
{
while (str[i]==' ')
i++;
}
if (str[i] == '[') //checks if it is array//
{
printf("%c", str[i]);
i++;
while (str[i] != ']')
{
tempChar[j] = str[i]; //copies the value in the string//
i++;
j++;
}
tempChar[j] = '\0';
temp = strToNumber(tempChar); //converting to number in order to valuate the bytes//
}
printf("%c", str[i]);
i++;
if (isspace(str[i]))
{
while (isspace(str[i]))
i++;
}
}
fprintf(f," requires %d bytes \n", temp*(sizeof(temp)));
}
if (str[i] == '*') //for pointers//
{
while (str[i] != ',' && str[i] != ';')
{
printf("%c", str[i]);
i++;
if (str[i]==' ')
{
while (str[i]==' ')
i++;
}
}
fprintf(f," requires %d bytes \n", 4);
}
if (str[i] != ';')
i++;
}
fclose(f);
}
int theSizeOf(char* str) // checking the size of the variable
{
if (strcmp(str, "int")==0 || strcmp(str, "long")==0 || strcmp(str, "float")==0)
return 4;
else if (strcmp(str, "char")==0)
return 1;
else if (strcmp(str, "double")==0)
return 8;
else if (strcmp(str, "short")==0)
return 2;
else
return 0;
}
int strToNumber(char* str) //converting the string to number//
{
int temp=1;
int num=0;
int t;
int i;
int length = strlen(str);
for (i = length-1; i >= 0; i--)
{
t = str[i] - '0';
num += t * temp;
temp *= 10;
}
return num;
}
thank you all for your help!
example of using sscanf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFF_SIZE 128
void bytesPerValue(FILE *ofp, char str[]);
int main(int argc, char *argv[]){
char str[BUFF_SIZE];
char *inp_filename, *out_filename;
FILE *ifp, *ofp;
if(argc != 3){
fprintf(stderr, "Usage: %s input_filename output_filename\n", argv[0]);
return EXIT_FAILURE;
}
inp_filename = argv[1], out_filename = argv[2];
if(NULL==(ifp = fopen(inp_filename, "r"))){
fprintf(stderr, "Couldn't open file : %s\n", inp_filename);
return EXIT_FAILURE;
}
if(NULL==(ofp = fopen(out_filename, "w"))){
fprintf(stderr, "Couldn't open file : %s\n", out_filename);
return EXIT_FAILURE;
}
while(fgets(str, sizeof str, ifp)){
//str[strcspn(str, "\n")] = 0;//chomp newline
bytesPerValue(ofp, str);
}
fclose(ifp), fclose(ofp);
}
struct size_of_type {
const char *name;
int size;
} Type_size[] = {
{ "char" , sizeof(char) },
{ "double", sizeof(double) },
{ "float" , sizeof(float) },
{ "int" , sizeof(int) },
{ "long" , sizeof(long) },
{ "short" , sizeof(short) },
};
int cmp(const void *a, const void *b){
return strcmp(*(char **)a, *(char **)b);
}
int theSizeOf(const char *type){
struct size_of_type *stp;
if(!*type)//""
return 0;
stp = bsearch(&type, Type_size, sizeof(Type_size)/sizeof(*Type_size), sizeof(*Type_size), cmp);
return stp ? stp->size : -1;
}
enum { UNKNOWN = -1, NONE };
#define UNDER_BAR "_"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define ID_CHARS UPPERCASE LOWERCASE UNDER_BAR
void bytesPerValue(FILE *fp, char str[]) {
char type[16] = "", rest[BUFF_SIZE];
char field[BUFF_SIZE], id[BUFF_SIZE], dummy[BUFF_SIZE];
char *sp, sep=0, end_b, dispname[BUFF_SIZE];
int typeSize, size, subscript, len;
sscanf(str, "%s %[^\n]", type, rest);
typeSize = theSizeOf(type);
if(typeSize == UNKNOWN){
fprintf(fp, "%s is unknown type in '%s'\n", type, str);
return;
} else if(typeSize == NONE){//blank line
return;
}
sp = rest;
for(sp = rest; 2 == sscanf(sp, " %[^,;]%c%n", field, &sep, &len) && (sep == ',' || sep == ';'); sp += len){
if(3 == sscanf(field, " * %[" ID_CHARS "] [%d %c %s", id, &subscript, &end_b, dummy) && subscript > 0 && end_b == ']'){//array of pointer
typeSize = sizeof(void *);
size = typeSize * subscript;
sprintf(dispname, "*%s[]", id);
}
else if(3 == sscanf(field, " %[" ID_CHARS "] [%d %c %s", id, &subscript, &end_b, dummy) && subscript > 0 && end_b == ']'){//array
size = typeSize * subscript;
sprintf(dispname, "%s[]", id);
}
else if(1 == sscanf(field, " * %[" ID_CHARS "] %s", id, dummy)){//pointer
size = typeSize = sizeof(void *);
sprintf(dispname, "*%s", id);
}
else if(1 == sscanf(field, " %[" ID_CHARS "] %s", id, dummy)){//normal variable
size = typeSize;
strcpy(dispname, id);
} else {
fprintf(fp, "'%s' is invalid format.\n", field);
continue;
}
fprintf(fp, "%s requires %d bytes \n", dispname, size);
}
if(sep != ';'){
fprintf(fp, "'%s' is invalid format.\n", str);
}
}

Creating an array of strings - c

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main()
{
char str[1000], *arr;
int i = 0,len,counter=0,j=0;
arr = (char*)malloc((sizeof(char*) * 1000));
for (i = 0; str[i] != '\0'; i++)
{
str[i] = getchar();
if (str[i] == ' ')
{
str[i] = '\0';
arr[j] = malloc(sizeof(char)*counter);
strcpy_s(&arr[j], counter * sizeof(char), &str[i - counter]);//i dont know why but this line does me some problems
j++;
counter = 0;
}
counter++;
}
}
I am trying to create an array of strings but the strcpy is not letting me and i do not know why. help will be much appreciated.
This error is because str[i - counter] is a char, not a pointer. You need to write &str[i - counter] or (str + i - counter).
See the signature of strcpy_s: errno_t strcpy_s(char *restrict dest, rsize_t destsz, const char *restrict src);
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int count_spaces(char *str)
{
int count = 0;
if (str == NULL || strlen(str) == 0)
return (0);
int i = 0;
while (str[i])
{
if (str[i] == ' ')
count++;
i++;
}
return count++;
}
char **get_strings(char *str)
{
if (str == NULL || strlen(str) == 0)
return NULL;
char **dest;
if ((dest = malloc(sizeof(char*) * (count_spaces(str) + 1))) == NULL || (dest[0] = malloc(sizeof(char) * (strlen(str) + 1))) == NULL)
return NULL;
int i = 0, j = 0, k = 0;
while (str[i])
{
if (str[i] == ' ')
{
dest[k][j] = '\0';
j = 0;
dest[++k] = malloc(sizeof(char) * (strlen(str) + 1));
}
else
dest[k][j++] = str[i];
i++;
}
dest[k + 1] = NULL;
return dest;
}
int main()
{
char **dest;
dest = get_strings("this is a test for stackoverflow");
int i = 0;
while (dest[i] != NULL)
printf("%s\n", dest[i++]);
}
here is a quick (non-perfect) example to do it with char **
you give a string as parameter and the function will store each segment using space as delimiter in a char **
you can print it as i did in the main. Don't forget to free when you're done

Program that returns words that ends and starts with the same letter

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.

Segmentation fault(core dumped) - cPointers [C]

I was assigned with a task of completing an assignment in C, without being taught C. (I have been learning Java) I am not sure how to fix this error nor do I know what the error means.
#include <stdio.h>
//int mystrcmp(char * s, char * t);
int main(int argc, char * argv[])
{
// #1 Prints out cmd line arguments
int i;
for (i = 0; i < argc; ++i)
{
printf("%s\n",argv[i]);
}
printf("\n"); //Spaceholder
// #2 String Compare
printf("%s %s\n", argv[1], argv[2]);
printf("Returned Value: %d\n", mystrcmp(argv[1], argv[2]));
//mystrcmp(argv[1],argv[2]);
// #3 String Concatenate
printf("\n"); //Spaceholder
printf("String Concatenate: %s\n", mystrcat(argv[1]));
// #4 String Copy
printf("\n"); //Spaceholder
// printf("String Copy: %s\n" , mystrcpy(argv[1]));
}
///////////
//Methods//
///////////
/* srtcmp: return < 0 if s < t, 0 if s==t, > 0 if s > t */
int mystrcmp(char * s, char * t)
{
int i;
for(i = 0; s[i] && s[2]; ++i)
{
if (s[i] == t[i] || (s[i]) == t[i])
continue;
else
break;
}
if (s[i] == t[i])
return 0;
if ((s[i]) < (t[i]))
return -1;
return 1;
}
mystrcat(char *dest, char *source)
{
int a = 0;
while(*(dest + a) != '\0')
{
a++;
}
int b = 0;
while(*(source + a) != '\0')
{
*(dest + a) = *(source + b);
a++;
b++;
}
}
mystrcpy(char * s, char * dest)
{
while((*s++ = *dest++)!= '\0')
;
return *dest;
}
I am assuming the error is coming from my mystrcat.
while(*(source + a) != '\0')
should be
while(*(source + b) != '\0')

Replace char in string with another string in C

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.

Resources