Getting free() invalid pointer error, when reading file and string joining - c

So I have this function
char *read_file(int fd)
{
char *str;
char *buffer;
int bytes;
buffer = malloc(sizeof(char) * 101);
if (!buffer)
return (NULL);
bytes = read(fd, buffer, 100);
while (bytes != 0)
{
if (bytes == -1)
{
free(buffer);
return (NULL);
}
buffer[bytes] = '\0';
str = ft_strjoin(str, buffer);
bytes = read(fd, buffer, 100);
}
free(buffer);
return (str);
}
It calls this function ft_strjoin
char *ft_strjoin(char *s1, char *s2)
{
char *str;
if (!s1 && !s2)
return (ft_strdup(""));
if (s1 && !s2)
{
str = ft_strdup(s1);
free(s1);
return (str);
}
if (!s1 && s2)
return (ft_strdup(s2));
if (!s2[0])
return (s1);
str = malloc(sizeof(char) * (ft_strlen(s1) + ft_strlen(s2) + 1));
if (!str)
return (NULL);
ft_memmove(str, s1, ft_strlen(s1));
ft_memmove(str + ft_strlen(s1), s2, ft_strlen(s2));
str[ft_strlen(s1) + ft_strlen(s2)] = '\0';
free(s1);
return (str);
}
The reason why I free s1 is because the previous string will be malloced so I free the previous string and return the new string. How ever it's causing an error free() invalid pointer. If I remove the free(s1) at the end of ft_strjoin the error goes away but I need to free the previous string, so what do I do. ft_strdup just mallocs a new string, duplicates the argument, and copies it to the new malloced string and returns the new malloced string. ft_memmove does what memmove does.

Your function can be reduced to:
char *read_file(int fd)
{
char *str = NULL;
struct stat st;
if(fstat(fd, &st) != -1)
{
str = malloc(st.st_size);
if(str)
{
if(read(fd, str, st.st_size) != st.st_size)
{
/* error handling */
}
}
}
return str;
}
ft_strjoin is much too complicated. You should not free any memory in this kind general function. Use memcpy (or your version) to copy.
char *ft_strjoin(const char * restrict s1, const char * restrict s2)
{
char *str;
size_t s1len = s1 ? ft_strlen(s1) : 0, s2len = s2 ? ft_strlen(s2) : 0;
size_t newsize = s1len + s2len + 1;
str = malloc(newsize);
if(str)
{
if(s1) ft_memcpy(str, s1, s1len);
if(s2) ft_memcpy(str + s1len, s2, s2len);
str[newsize - 1] = 0;
}
return str;
}

Related

Memory leak in C with static variable and i dont know how to fix it

As an exercise i'm writing a C function to read content from a file descriptor one line at a time.
In the exercise i'm only allowed to use read(), malloc() and free() from the standard library, while using one static variable. The function works but i keep getting a persistent memory leak when i reach the last line in the file that i cant seem to solve.
Leak:
Direct leak of 1 byte(s) in 1 object(s) allocated from:
#0 0x7f37f253a4bf in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/12/libasan.so.8+0xbd4bf)
#1 0x5644d5df4735 in offset /home/practical/Documents/Code/42/get_next_line/get_next_line.c:71
#2 0x5644d5df49ba in get_next_line /home/practical/Documents/Code/42/get_next_line/get_next_line.c:116
#3 0x5644d5df4a8b in main /home/practical/Documents/Code/42/get_next_line/get_next_line.c:138
#4 0x7f37f22cd189 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).
Code:
#include "get_next_line.h"
#include <stdlib.h>
#include <unistd.h>
// needed for main:
#include <stdio.h>
#include <fcntl.h>
// finds the first line ending in \n from buffer
// this is the line for get_next_line to return
char *next_line(char *a)
{
int i;
char *buf;
if (!a || !a[0])
return (NULL);
i = 0;
while (a[i] && a[i] != '\n')
i++;
if (a[i] == '\n')
i++;
buf = (char *)malloc((sizeof(char) * i) + 1);
if (!buf)
return (NULL);
i = 0;
while (a[i] && a[i] != '\n')
{
buf[i] = a[i];
i++;
}
if (a[i] == '\n')
buf[i++] = '\n';
buf[i] = '\0';
return (buf);
}
// finds the end of the line we just returned in the buffer
// moves it to the end of new buffer
// changes the \n before it to '\0', so our new buffer does not contain it
// this offsets our buffer, the buffer now starts
// at the next line to be printed
char *offset(char *a)
{
char *buf;
int i;
int x;
i = 0;
x = 0;
while (a[i] && a[i] != '\n')
i++;
if (a[i] == '\0')
{
free(a);
return (NULL);
}
if (a[i] == '\n')
i++;
buf = (char *)malloc(ft_strlen(a) - i + 1);
if (!buf)
return (NULL);
while (a[i + x])
{
buf[x] = a[i + x];
x++;
}
buf[x] = '\0';
free(a);
return (buf);
}
// static buffer str starts at the next line to be printed
// we use strchr to find if there is a \n in the buffer
// if theres not, we read from the file into the buffer
// if \n is present, this is the line to print
// next_line then gets the first line ending in '\n' from the static buffer
// we return this line
// then we offset the static buffer by the line we just returned
char *get_next_line(int fd)
{
static char *str;
char *buf;
int i;
if (fd < 0 || BUFFER_SIZE <= 0)
return (NULL);
buf = (char *)malloc((sizeof(char) * BUFFER_SIZE) + 1);
if (!buf)
return (NULL);
i = 1;
while (!(ft_strchr(str, '\n')) && i != 0)
{
i = read(fd, buf, BUFFER_SIZE);
if (i == -1)
{
free(buf);
return (NULL);
}
buf[i] = '\0';
str = ft_strjoin(str, buf);
}
free(buf);
buf = next_line(str);
str = offset(str);
return (buf);
}
int main(int argc, char *argv[])
{
char *line;
int fd;
if (argc < 2)
{
printf("Usage: %s <file>\n", argv[0]);
return (1);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("Failed to open file");
return (1);
}
while (line != NULL)
{
line = get_next_line(fd);
printf("%s", line);
free(line);
}
close (fd);
return (0);
}
ft_strjoin
char *ft_strdup(char *src)
{
char *dst;
int i;
i = 0;
dst = malloc(ft_strlen(src) + 1);
if (!dst)
return (NULL);
while (src[i])
{
dst[i] = src[i];
i++;
}
dst[i] = '\0';
return (dst);
}
char *ft_strcat(char *dest, char *src)
{
int i;
int l;
i = 0;
l = ft_strlen(dest);
while (src[i] != '\0')
{
dest[i + l] = src[i];
i++;
}
dest[i + l] = '\0';
return (dest);
}
char *ft_strjoin(char const *s1, char const *s2)
{
char *str;
size_t len;
if (!s1 && !s2)
return (ft_strdup(""));
if (s1 && !s2)
return (ft_strdup((char *)s1));
if (!s1 && s2)
return (ft_strdup((char *)s2));
len = ft_strlen((char *)s1) + ft_strlen((char *)s2);
str = malloc(sizeof(char) * (len + 1));
if (!str)
return (NULL);
str[0] = '\0';
ft_strcat(str, (char *)s1);
ft_strcat(str, (char *)s2);
return (str);
}
Problem
I went over the code and it seems that i am freeing everything.
I think the issue may be with returning buf in the get_next_line function, which gets allocated by the next_line function. I cant free this because i am returning it, but i am freeing the string later in the main().
Maybe i should be freeing the static variable after i reach the end of the file i'm reading from the descriptor?
Any suggestions appreciated, thanks
"seems that i am freeing everything" --> code does not free str in get_next_line() when done.

Trying to replace text in files throws a error

The point of the script is to take three parameters. Find, replace, prefix. Find being the text to replace, replace being what to replace the text with, and prefix is a special case. If prefix is in the text, you replace the prefix (some text) with prefix+replace. I would like to know why the below code throws a error right after saying opened file. It only seems to throw an error if the text being replaced is repeated like "aaa", "bbb" where "a" is what is being replaced.
Opened file.txt
*** Error in `./a.out': malloc(): memory corruption: 0x00005652fbc55980 ***
There's also the occasionally seg fault after printing "Trying to replace for file ...". I'm not fluent in C and GDB on my system resulted in just missing library errors which has nothing to do with this.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
char concat(const char *s1, const char *s2)
{
char *result = calloc(strlen(s1)+strlen(s2)+1, 1);
strcpy(result, s1);
strcat(result, s2);
printf("Prefix will be replaced with %s.\n", result);
return result;
}
static int replaceString(char *buf, const char *find, const char *replace, const char *prefix)
{
int olen, rlen;
char *s, *d;
char *tmpbuf;
if (!buf || !*buf || !find || !*find || !replace)
return 0;
tmpbuf = calloc(strlen(buf) + 1, 1);
if (tmpbuf == NULL)
return 0;
olen = strlen(find);
rlen = strlen(replace);
s = buf;
d = tmpbuf;
while (*s) {
if (strncmp(s, find, olen) == 0) {
strcpy(d, replace);
s += olen;
d += rlen;
}
else
{
*d++ = *s++;
}
}
*d = '\0';
if(strcmp(buf, tmpbuf) == 0)
{
free(tmpbuf);
return 0;
}
else
{
strcpy(buf, tmpbuf);
free(tmpbuf);
printf("%s", buf);
printf("Replaced!\n");
return 1;
}
}
void getAndReplace(char* filename, char* find, char* replace, char* prefix)
{
long length;
FILE* f = fopen (filename, "r");
char* buffer = 0;
if (f)
{
fseek (f, 0, SEEK_END);
length = ftell (f);
fseek (f, 0, SEEK_SET);
buffer = calloc(length+1, 1); //If i use malloc here, any file other than the first has garbage added to it. Why?
if (buffer)
{
fread(buffer, 1, length, f);
}
fclose(f);
}
if(buffer)// && strlen(buffer) > 1)
{
int result = replaceString(buffer, find, replace, prefix);
if(result == 0)
{
printf("Trying to replace prefix.\n");
replace = concat(prefix, replace);
result = replaceString(buffer, prefix, replace, "");
}
else
{
printf("Successfully replaced %s with %s\n", find, replace);
}
if(result == 1)
{
FILE* fp = fopen(filename, "w+");
if(fp)
{
printf("Opened %s\n", filename);
fprintf(fp, buffer);
fclose(fp);
printf("File %s overwritten with changes.\n", filename);
}
}
else
{
printf("Nothing to replace for %s\n", filename);
}
}
else
{
printf("Empty file.");
}
if(buffer)
{
free(buffer);
}
}
int main(int argc, char **argv)
{
if(argc < 4)
{
printf("Not enough arguments given: ./hw3 <find> <replace> <prefix>\n");
return 1;
}
struct dirent *de;
DIR *dr = opendir(".");
if (dr == NULL)
{
printf("Could not open current directory\n");
return 0;
}
while ((de = readdir(dr)) != NULL)
{
if(strlen(de->d_name) > 4 && !strcmp(de->d_name + strlen(de->d_name) - 4, ".txt"))
{
printf("Trying to replace for file %s\n", de->d_name);
getAndReplace(de->d_name, argv[1], argv[2], argv[3]);
}
}
closedir(dr);
return 0;
}
I hope that you concat function
char concat(const char *s1, const char *s2);
is just a typo and you meant
char *concat(const char *s1, const char *s2);
otherwise the function would be returning a pointer as if it were a char.
Using valgrind would give more details where exactly you are reading/writing where you are not allowed to and
where you are leaking memory. Without that it's hard to pinpoint the exact
place. One thing I noticed is that depending on the length of find and replace,
you might not have enough memory for tmpbuf which would lead to a buffer
overflow.
I think that the best way to write the replaceString is by making it
allocate the memory it needs itself, rather than providing it a buffer to write into.
Because you are getting both find and replace from the user, you don't know
how large the resulting buffer will need to be. You could calculate it
beforehand, but you don't do that. If you want to pass a pre-allocated buffer to
replaceString, I'd pass it as a double pointer, so that replaceString can do
realloc on it when needed. Or allocate the memory in the function and return a
pointer to the allocated memory.
This would be my version:
char *replaceString(const char *haystack, const char *needle, const char *replace)
{
if(haystack == NULL || needle == NULL || replace == NULL)
return NULL;
char *dest = NULL, *tmp;
size_t needle_len = strlen(needle);
size_t replace_len = strlen(replace);
size_t curr_len = 0;
while(*haystack)
{
char *found = strstr(haystack, needle);
size_t copy_len1 = 0;
size_t new_size = 0;
size_t pre_found_len = 0;
if(found == NULL)
{
copy_len1 = strlen(haystack) + 1;
new_size = curr_len + copy_len1;
} else {
pre_found_len = found - haystack;
copy_len1 = pre_found_len;
new_size = curr_len + pre_found_len + replace_len + 1;
}
tmp = realloc(dest, new_size);
if(tmp == NULL)
{
free(dest);
return NULL;
}
dest = tmp;
strncpy(dest + curr_len, haystack, copy_len1);
if(found == NULL)
return dest; // last replacement, copied to the end
strncpy(dest + curr_len + pre_found_len, replace, replace_len + 1);
curr_len += pre_found_len + replace_len;
haystack += pre_found_len + needle_len;
}
return dest;
}
The idea in this version is similar to yours, but mine reallocates the memory as
it goes. I changed the name of the arguments to have the same name as the
strstr function does based on my documentation:
man strstr
char *strstr(const char *haystack, const char *needle);
Because I'm going to update haystack to point past the characters copied, I
use this loop:
while(*haystack)
{
...
}
which means it is going to stop when the '\0'-terminating byte is reached.
The first thing is to use strstr to locate a substring that matches needle.
Base on whether a substring is found, I calculate how much bytes I would need to
copy until the substring, and the new size of the buffer. After that I
reallocate the memory for the buffer and copy everything until the substring,
then append the replacement, update the curr_len variable and update the
haystack pointer to point past the substring.
If the substring is not found, no more replacements are needed. So we have to
copy the string pointed to by haystack and return the constructed string. The
new size of the destination is curr_len + strlen(haystack) + 1 (the +1
because I want the strncpy function to also copy the '\0'-terminating byte).
And it has to copy strlen(haystack) + 1 bytes. After the first strncpy, the
function returns dest.
If the substring is found, then we have to copy everything until the substring,
append the replacement and update the current length and the haystack pointer.
First I calculate the string until the found substring and save it in
pre_found_len. The new size of the destination will be
curr_len + pre_found_len + replace_len + 1 (the current length + length of
string until substring + the length of the replacement + 1 for the
'\0'-terminating byte). Now the first strncpy copies only pre_found_len
bytes. Then it copies the replacement.
Now you can call it like this:
int main(void)
{
const char *orig = "Is this the real life? Is this just fantasy?";
char *text = replaceString(orig, "a", "_A_");
if(text)
{
puts(orig);
puts(text);
}
free(text);
}
which will output:
Is this the real life? Is this just fantasy?
Is this the re_A_l life? Is this just f_A_nt_A_sy?
Now you can use this function in getAndReplace to replace the prefix:
char *getAndReplace(char* filename, char* find, char* replace, char* prefix)
{
...
char *rep1 = replaceString(buffer, find, replace);
if(rep1 == NULL)
{
// error
free(buffer);
return NULL;
}
char *prefix_rep = malloc(strlen(replace) + strlen(prefix) + 1);
if(prefix_rep == NULL)
{
// error
free(buffer);
free(rep1);
return NULL;
}
sprintf(prefix_rep, "%s%s", replace, prefix);
char *rep2 = replaceString(rep1, prefix, prefix_rep);
if(rep2 == NULL)
{
// error
free(buffer);
free(rep1);
free(prefix_rep);
return NULL;
}
// rep2 has all the replacements
...
// before leaving
free(buffer);
free(rep1);
free(prefix_rep);
// returning all replacements
return rep2;
}
When using malloc & co, don't forget to check if they return NULL and don't
forget to free the memory when not needed.

C trying to copy pointer to a new pointer

I need help with a couple of things:
I'm trying to delete a word from a pointer and put it in a new pointer with a new length but i am not able to copy it to the new pointer
I'm not sure when should I use the free() function.
when I use the free(str) in the delete function it crashes.
After I copy the "str" to the "newStr" what is the best way to copy the "newStr" back to the "str" with the new length?
Please help me understand it, I'm new with this and I googled it, I tried looking here and didn't find something that could help me.
void delete(char *str)
{
int i, indexStart = 0, indexEnd = 0, wordlen = 0, newLen = 0, len = 0;
printf("Enter the index of the word that you want to remove: ");
scanf("%d", &i);
indexs(i, str,&indexStart,&indexEnd,&wordlen);
len = strlen(str);
newLen = len - wordlen - 1;
char *newStr = (char*)malloc(newLen * sizeof(char));
if (newStr == NULL)
{
printf("Error! memory not allocated.");
exit(0);
}
for (int j = 0; j < len; j++)
{
if (j< (indexStart - 1) || j > indexEnd)
{
*newStr = *str;
newStr++;
}
str++;
}
free(str);
//free(newStr);
printf("The new string: %s\n", newStr);
}
void main()
{
char *str = (char*)malloc(1 * sizeof(char));
if (str == NULL)
{
printf("Error! memory not allocated.");
exit(0);
}
text(str);
if (str != NULL)
{
delete(str);
}
free(str);
system("pause");
}
According to the structured programming paradigm your functions should solve small separate tasks. But your function delete() prints to the console, scans input, allocates new string and fills this new string. But what's event worse is the call exit() in this function. If something went wrong, function must to return an error, but not to stop the program. Also names of functions should relfect what they do.
Use free() for every memory block allocated by malloc().
So, this is a working code:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
const char *findWord(const char *str, const char *delimiters, unsigned index) {
// validate input parameters
if (!str || !delimiters) {
return NULL;
}
// count words
unsigned count = 0;
while (*str && count < index) {
// skip delimiters
while (*str && !strchr(delimiters, *str)) {
str++;
}
if (*str) {
count++;
}
// skip word
while (*str && strchr(delimiters, *str)) {
str++;
}
}
// if index is too big returns NULL
return *str ? str : NULL;
}
unsigned countLengthOfWord(const char *str, const char *delimiters) {
// validate input parameters
if (!str || !delimiters) {
return 0;
}
// count length
unsigned length = 0;
while (*str && !strchr(delimiters, *str++)) {
length++;
}
return length;
}
char *cutWord(char *str, const char *delimiters, unsigned index) {
// validate input parameters
if (!str) {
return NULL;
}
str = (char *)findWord(str, delimiters, index);
// if index is too big, return NULL
if (!str) {
return NULL;
}
// allocate new string for word
unsigned length = countLengthOfWord(str, delimiters);
char *word = malloc(length + 1);
// check if allocation was successfull
if (!word) {
return NULL;
}
// copy word
strncpy(word, str, length);
word[length] = '\0';
// cut word from string
const char *ptr = str + length;
while (*ptr) {
*str++ = *ptr++;
}
*str = '\0';
return word;
}
int main() {
char str1[] = "Hello, my world!";
char str2[] = "Hello, my world!";
char str3[] = "Hello, my world!";
char *word1 = cutWord(str1, " ,!", 0);
char *word2 = cutWord(str2, " ,!", 1);
char *word3 = cutWord(str3, " ,!", 2);
if (word1) {
printf("word: %s\nstring: %s\n\n", word1, str1);
}
if (word2) {
printf("word: %s\nstring: %s\n\n", word2, str2);
}
if (word3) {
printf("word: %s\nstring: %s\n\n", word3, str3);
}
// release allocated memory
free(word1);
free(word2);
free(word3);
getchar();
return 0;
}

Leak of memory in C

In this function, I have leak of memory
static int read_buffer(int const fd, char **buffer)
{
char buff[BUFF_SIZE + 1];
int ret;
ret = read(fd, buff, BUFF_SIZE);
if (ret > 0)
{
buff[ret] = 0;
if (!(*buffer = ft_strjoin(*buffer, buff)))
return (-1);
}
return (ret);
}
I tried to do this and more solution again.. But I get also leak of memory
static int read_buffer(int const fd, char **buffer)
{
char buff[BUFF_SIZE + 1];
char *tmp;
int ret;
ret = read(fd, buff, BUFF_SIZE);
tmp = *buffer;
if (ret > 0)
{
buff[ret] = 0;
if (!(*buffer = ft_strjoin(*buffer, buff)))
return (-1);
free(tmp);
}
return (ret);
}
Here is ft_strjoin function: (can't modify)
char *ft_strjoin(char const *s1, char const *s2)
{
size_t size_s1;
size_t size_s2;
char *strjoin;
size_s1 = ft_strlen(s1);
size_s2 = ft_strlen(s2);
if (!(strjoin = malloc(size_s1 + size_s2 + 1)))
return (NULL);
ft_strcpy(strjoin, s1);
ft_strcat(strjoin, s2);
return (strjoin);
}
How I can resolve this ?
Thank you !
Anytime a function returns malloc'd memory, you've got a hot potato. You have to free that memory and cannot pass it on unless you've documented you're doing so. And you mustn't lose hold of (e.g. reuse) the pointer before freeing it. Below is how I interpret how read_buffer() needs to work. Since "buffer length is unknown" I'm assuming it comes from malloc and we can use realloc:
static int read_buffer(int const fd, char **buffer)
{
char local_buffer[BUFF_SIZE + 1];
int bytes_read = read(fd, local_buffer, BUFF_SIZE);
if (bytes_read > 0)
{
local_buffer[bytes_read] = '\0';
char *joined = ft_strjoin(*buffer, local_buffer);
if (joined != NULL)
{
*buffer = realloc(*buffer, strlen(joined) + 1);
if (*buffer != NULL)
{
ft_strcpy(*buffer, joined);
}
else
{
bytes_read = -1;
}
free(joined);
}
else {
bytes_read = -1;
}
}
return bytes_read;
}
Note that there are a lot of potential pitfalls that you need to test for and recover from.
If you're reading from the user directly, and don't want newlines as part of the concatenation of strings, you can replace this line:
local_buffer[bytes_read] = '\0';
with something like:
if (local_buffer[bytes_read - 1] == '\n')
{
local_buffer[bytes_read - 1] = '\0';
}
else
{
local_buffer[bytes_read] = '\0';
}
Assuming the above newline fix, here's a small test program I wrote:
int main() {
char *buffer = malloc(1);
*buffer = '\0';
for (int i = 0; i < 3; i++)
{
(void) read_buffer(0, &buffer);
puts(buffer);
}
free(buffer);
return 0;
}
RESULT
> ./a.out
abcdefg
abcdefg
hijklmn
abcdefghijklmn
opqrstu
abcdefghijklmnopqrstu
>

how repeat a string in language C

how I do to repeat a string?
something like "hello world" * 3
the output "hello world hello world hello world"
In your source code, without much processing, probably the easiest way is with:
#define HI "hello world"
char str[] = HI " " HI " " HI;
This will declare a string of the requested value:
"hello world hello world hello world"
If you want code that will do it, you can use something like:
char *repeatStr (char *str, size_t count) {
if (count == 0) return NULL;
char *ret = malloc (strlen (str) * count + count);
if (ret == NULL) return NULL;
strcpy (ret, str);
while (--count > 0) {
strcat (ret, " ");
strcat (ret, str);
}
return ret;
}
Now keep in mind this can be made more efficient - multiple strcat operations are ripe for optimisation to avoid processing the data over and over (a). But this should be a good enough start.
You're also responsible for freeing the memory returned by this function.
(a) Such as with:
// Like strcat but returns location of the null terminator
// so that the next myStrCat is more efficient.
char *myStrCat (char *s, char *a) {
while (*s != '\0') s++;
while (*a != '\0') *s++ = *a++;
*s = '\0';
return s;
}
char *repeatStr (char *str, size_t count) {
if (count == 0) return NULL;
char *ret = malloc (strlen (str) * count + count);
if (ret == NULL) return NULL;
*ret = '\0';
char *tmp = myStrCat (ret, str);
while (--count > 0) {
tmp = myStrCat (tmp, " ");
tmp = myStrCat (tmp, str);
}
return ret;
}
You could use sprintf.
char s[20] = "Hello";
char s2[20];
sprintf(s2,"%s%s%s",s,s,s);
I've made this function based on earlier answers in this post.
I share it here because some of previous examples has been thrown me segfaults
const char* str_repeat(char* str, size_t times)
{
if (times < 1) return NULL;
char *ret = malloc(sizeof(str) * times + 1);
if (ret == NULL) return NULL;
strcpy(ret, &str);
while (--times > 0) {
strcat(ret, &str);
}
return ret;
}
http://ideone.com/5sNylW
#include <stdio.h>
#include <string.h>
int main(void) {
char k[100];
gets(k);
int lk=strlen(k);
int times;
scanf("%d",&times);
int tl= times*lk;
int i,x=0;
for(i=lk-1;i<tl;i++)
{
k[i+1]=k[x];
x++;
}
for(i=0;i<tl;i++)
{
printf("%c",k[i]);
}
return 0;
}
You may try write own function. It will be work with single-length string also (i. e. duplication a single char). It use the function "strcat()" from the "string.h", so do not forget include this header.
char *
str_repeat(char str[], unsigned int times)
{
if (times < 1)
return NULL;
char *result;
size_t str_len = strlen(str);
result = malloc(sizeof(char) * str_len + 1);
while (times--) {
strcat(result, str);
}
return result;
}
But, if you need only duplication of a string for print it, try macro
#define PRINT_STR_REPEAT(str, times) \
{ \
for (int i = 0; i < times; ++i) \
printf("%s", str); \
puts(""); \
}
Results
PRINT_STR_REPEAT("-", 10); // ----------
puts(str_repeat("-", 10)); // ----------
PRINT_STR_REPEAT("$", 2); // $$
puts(str_repeat("$", 2)); // $$
PRINT_STR_REPEAT("*\t*", 10); // * ** ** ** ** ** ** ** ** ** *
puts(str_repeat("*\t*", 10)); // * ** ** ** ** ** ** ** ** ** *
PRINT_STR_REPEAT("*_*", 10); // *_**_**_**_**_**_**_**_**_**_*
puts(str_repeat("*_*", 10)); // *_**_**_**_**_**_**_**_**_**_*
Here's a way to repeat a string in C, N times.
That is have a string "abc"
and I want a string of length 7 that is comprised of this string repeated.
N = 7;
result: "abcabca"
while(Index != N){
repeatedString[Index] = oldString[Index%strlen(oldString)];
Index++;
}
Where repeated String would be "abcabca" at the end, and oldString is "abc".

Resources