Ok, so I have a char stringA and char stringB, and I want to be able to insert stringB into stringA at point x.
char *stringA = "abcdef";
char *stringB = "123";
with a product of "ab123cdef"
does anyone know how to do this? Thanks in advance
char * strA = "Blahblahblah", * strB = "123", strC[50];
int x = 4;
strncpy(strC, strA, x);
strC[x] = '\0';
strcat(strC, strB);
strcat(strC, strA + x);
printf("%s\n", strC);
Explanation:
You declare the two strings you will be joining, plus a third string into which you will put them.
You declare an integer to tell the program after how many characters you wish to insert the second string into the first.
The strncpy function copies the first x characters into strC. You have to add the null ('\0') character at the end, otherwise you'll probably get rubbish.
Strcat to copy the second string.
Another strcat to copy the remaining part of the first string (strA + x).
Hope that helps.
Remark: remember to make strC long enough to contain both strA and strC, otherwise you'll produce a segmentation fault. You may do this by declaring the string as an array, like in my example.
stringA and stringB are both pointers - they contain the starting address for a blob of memory. The memory they are pointing to contain continuous strings of characters: "abcdef" and "123" respectively. Since strings are contiguous blocks memory (meaning that the memory location of a given character is one byte after the previous) you can't insert more characters into the middle of a string without first moving some characters. In your case you can't even really do this, since the amount of memory allocated for each string is exactly large enough to hold JUST that string (ignoring padding).
What you are going to have to do is copy the strings to another block of memory, one that you have allocated for that purpose, and copy them so that the second string starts x characters into the first string.
Several other SO users have posted code-solutions but I think you should try and find the exact solution on your own (and hopefully my high-level explanation of what's going on will help).
Here a more general solution.
Note that destination must have enough space in memory to add seed (e.g. an heap-allocated array of size grater than strlen(seed)+strlen(destination) ). So, concerning the question, you have to create a larger array.
/*
destination: a NULL terminated string
pos: where insert seed
seed: a NULL terminated string
*/
void insertString(char* destination, int pos, char* seed)
{
char * strC;
strC = (char*)malloc(strlen(destination)+strlen(seed)+1);
strncpy(strC,destination,pos);
strC[pos] = '\0';
strcat(strC,seed);
strcat(strC,destination+pos);
strcpy(destination,strC);
free(strC);
}
int insert_pos = 5;
int product_length = strlen(stringA) + strlen(stringB) + 1;
char* product = (char*)malloc(product_length);
strncpy(product, stringA, insert_pos);
product[insert_pos] = '\0';
strcat(product, stringB);
strcat(product, stringA + insert_pos);
...
free(product);
char *strInsert(char *str1, const char *str2, int pos) {
size_t l1 = strlen(str1);
size_t l2 = strlen(str2);
if (pos < 0) pos = 0;
if (pos > l1) pos = l1;
char *p = str1 + pos;
memmove(p + l2, p, l1 - pos);
memcpy (p, str2, l2);
return str1;
}
Related
I will say honestly, this isn't my code. It's my brother's who's studying with me but he's a ahead of me.
Please notice char *str and char *resultString in the function char *replaceWord().
/*Suppose you have a template letter.txt. You have to fill in values to a template. Letter.txt looks something like this:
Thanks {{name}} for purchasing {{item}} from our outlet {{outlet}}. Please visit our outlet {{outlet}} for any kind of problems. We plan to serve you again soon.
You have to write a program that will automatically fill the template.For this, read this file and replace these values:
{{name}} - Harry
{{item}} - Table Fan
{{outlet}} - Ram Laxmi fan outlet
Use file functions in c to accomplish the same.*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * replaceWord(const char * str, const char * oldWord, const char * newWord)
{
char * resultString;
int i, count = 0;
int newWordLength = strlen(newWord);
int oldWordLength = strlen(oldWord);
for (i = 0; str[i] != '\0'; i++)
{
if (strstr(&str[i], oldWord) == &str[i])
{
count++;
//Jumping over the word and continuing
i = i + oldWordLength - 1;
}
}
//dynamically allocation memory to resultString since it can be big or samll depending on the size of the newWord.
/*i = old string length , count = no. of times the word appeared in the string,
newWordLength-oldWordLength=difference between the new word and the old word
+1 for the null character '\0'
Basically we are saying that add the size required for the newWord to the strings length i.e i;
*/
resultString = (char *)malloc(i + count * (newWordLength - oldWordLength) + 1);
i = 0; //refreshing the i for the while loop
while (*str)
{
if (strstr(str, oldWord) == str)
{
strcpy(&resultString[i], newWord);
i += newWordLength;
str += oldWordLength;
}
else
{
resultString[i] = *str;
i+=1;
str+=1;
}
}
resultString[i] = '\0';
return resultString;
}
int main()
{
FILE *ptr = NULL;
FILE *ptr2 = NULL;
ptr = fopen("letter.txt", "r"); //where the template is stored
ptr2 = fopen("newLetter.txt", "w"); //where the new bill will be stored.
char str[200];
fgets(str, 200, ptr); //store the bill template in the str variable.
printf("The original bill template is : %s\n", str);
//Calling the replacing fucntion
char *newStr = str; //newStr will store the new bill i.e generated
newStr = replaceWord(str, "{{name}}", "Mary");
newStr = replaceWord(newStr, "{{item}}", "Waffle Machine");
newStr = replaceWord(newStr, "{{outlet}}", "Belgium Waffle");
printf("\nThe bill generated is:\n%s", newStr);
fprintf(ptr2, "%s", newStr);
fclose(ptr);
fclose(ptr2);
return 0;
}
Can someone explain why the pointer *str and *resultString are expressed different ways in the program and what are they doing? Sometimes it's *str, &str or str[i].
Please explain.
I know that a pointer is used to keep the address of the other variables but this code is still a mystery to me.
Also why was the function a pointer?
NOTE:"He said that's how it works" when I asked how.
Please help!! I can't focus on other things.
If you can't explain ;a link of explanation would be fine as well.
Sometimes it's *str, &str or str[i]
Those are operators.
*str
str is a poitner to a char, and having a * over it dereferences it. Meaning it fetches the value from the memory that it is pointing to. A pointer may not always point to a variable though, it can be any arbitrary memory address. But dereferencing memory that is not yours will result in Segmentation fault which is the my most beloved error that occurs almost everytime when processing arrays.
str[i]
This is the same as *(str + i). Meaning it increments the memory address by i * sizeof(<datatype of what str points to>). Then it fetches the value from that incremented address. This is used for getting elements of an array.
&str
This just given the address of the variable str, which is a pointer. So, it returns a pointer to a pointer(ie. str). A pointer to a pointer can exist.
The function is not a pointer. Instead, it returns a pointer which is *resultString. It is so that a string can be returned. The string had been initialized in this line:
resultString = (char *)malloc(i + count * (newWordLength - oldWordLength) + 1);
The comment explaining this is not complete.
//dynamically allocation memory to resultString since it can be big or samll depending on the size of the newWord.
/*i = old string length , count = no. of times the word appeared in the string,
newWordLength-oldWordLength=difference between the new word and the old word
+1 for the null character '\0'
Basically we are saying that add the size required for the newWord to the strings length i.e i;
*/
It also misses one key reason why malloc is being used instead of normal allocation. malloc allocates your variables on the heap which is shared among all functions and threads. While normal initialization would allocate it on the stack which is popped off when the function ends. So, no use after the function with the stack, so it should be used on the heap. And it is also for dynamic allocation.
I have to do an exercise and I have this structure given:
typedef struct {
char *str;
unsigned int len;
} String;
My Task is to write a String Concat which concats "Kartoffel" and "puffer" to "Kartoffelpuffer" (potato fritter).
String concat(String l, String r)
Both Strings l and r should not be changed after running the function.
First I created the two Strings in the main:
String1 *l = malloc(sizeof(String1));
String1 *r = malloc(sizeof(String1));
(*l).str = malloc(sizeof("Kartoffel"));
(*r).str = malloc(sizeof("puffer"));
(*l).str = "Kartoffel";
(*r).str = "puffer";
(*l).len = 9;
(*r).len = 6;
Then I wrote the concat function:
String1 concat(String1 l, String1 r) {
unsigned int i = 0;
String1 *newStr = malloc(sizeof(String1));
/* +1 for '\0' at the end */
newStr->str = malloc(l.len + r.len + 1);
newStr->str = l.str;
/* The following line is not working */
newStr->str[l.len] = *r.str;
newStr->len = l.len + r.len;
return *newStr;
}
What Im trying to do is working with pointer arithmetic.
When there is a pointer which points to the beginning of a storage area like char *str, it should be possible to move the pointer with a[b] or *((a) + (b)) right? When I run the code I get Segmentation fault (I hope its the right translation. Original: "Speicherzugriffsfehler").
If someone could give me a hint I would be thankful. PS: Sorry for my English.
First, (*l).str = "Kartoffel"; makes (*l).str point to the "Kartoffel" string literal, meaning that the original memory allocated to (*l).str with malloc() is lost. Same for (*r).str = "puffer";. One of the things you can do to avoid this is copy the string into the allocated buffer by looping over the characters in a for loop (since you can't use string.h).
Then, in your concat() function, you do the same thing. You allocate the memory for newStr->str with malloc() (properly allocating an extra char for the null-terminator), but on the next line you re-assign that pointer to point to l.str, which is still pointing to the string literal. Then, with newStr->str[l.len] = *r.str; you are attempting to modify the string literal, which in C is undefined behavior.
The way to fix this could be, again, to copy the two strings into the buffer allocated with newStr->str = malloc(l.len+r.len+1);.
After allocating memeory to newStr and newStr->str
Two pointers could be used. char *to, *from;
Set the pointers with to = newStr->str; and from = l.str;
copy the characters with *to = *from;
Advance the pointers with to++; and from++;
Repeat until *from == 0
Set from with from = r.str;
to does not need to be reset as it is correctly positioned at the end of newStr->str.
Repeat the copy of characters.
Repeat advancing the pointers.
Set a terminating 0 with *to = 0;
Thank you very much for your help!
I wrote another method to copy the string as you guys said.
char * copyStr (char * dest,char * src){
unsigned int index;
for (index = 0; src[index] != '\0'; index++) {
dest[index] = src[index];
}
dest[index] = '\0';
return dest;
}
And I edited my concat like that:
String1 concat (String1 l, String1 r){
String1 *newStr = malloc(sizeof(String1));
newStr->str = malloc(l.len+r.len+1);
copyStr(newStr->str,l.str);
copyStr((newStr->str+l.len),r.str);
newStr->len = l.len+r.len;
return *newStr;
}
with newStr->str+l.len the pointer will be moved. If l.len is 9, the pointer will point to the 10th byte, which is the end of the first string l. So the the String r will be copied in the memory storage behind the first string l.
I need help with char array. I want to create a n-lenght array and initialize its values, but after malloc() function the array is longer then n*sizeof(char), and the content of array isnt only chars which I assign... In array is few random chars and I dont know how to solve that... I need that part of code for one project for exam in school, and I have to finish by Sunday... Please help :P
#include<stdlib.h>
#include<stdio.h>
int main(){
char *text;
int n = 10;
int i;
if((text = (char*) malloc((n)*sizeof(char))) == NULL){
fprintf(stderr, "allocation error");
}
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
int test = strlen(text);
printf("\n%d\n", test);
puts(text);
free(text);
return 0;
}
Well before using strcat make
text[0]=0;
strcat expects null terminated char array for the first argument also.
From standard 7.24.3.1
#include <string.h>
char *strcat(char * restrict s1,
const char * restrict s2);
The strcat function appends a copy of the string pointed to by s2
(including the terminating null character) to the end of the string
pointed to by s1. The initial character of s2 overwrites the null
character at the end of s1.
How do you think strcat will know where the first string ends if you don't
put a \0 in s1.
Also don't forget to allocate an extra byte for the \0 character. Otherwise you are writing past what you have allocated for. This is again undefined behavior.
And earlier you had undefined behavior.
Note:
You should check the return value of malloc to know whether the malloc invocation was successful or not.
Casting the return value of malloc is not needed. Conversion from void* to relevant pointer is done implicitly in this case.
strlen returns size_t not int. printf("%zu",strlen(text))
To start with, you're way of using malloc in
text = (char*) malloc((n)*sizeof(char)
is not ideal. You can change that to
text = malloc(n * sizeof *text); // Don't cast and using *text is straighforward and easy.
So the statement could be
if(NULL == (text = (char*) malloc((n)*sizeof(char))){
fprintf(stderr, "allocation error");
}
But the actual problem lies in
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
The strcat documentation says
dest − This is pointer to the destination array, which should contain
a C string, and should be large enough to contain the concatenated
resulting string.
Just to point out that the above method is flawed, you just need to consider that the C string "A" actually contains two characters in it, A and the terminating \0(the null character). In this case, when i is n-2, you have out of bounds access or buffer overrun1. If you wanted to fill the entire text array with A, you could have done
for(i = 0; i < n; i++){
// Note for n length, you can store n-1 chars plus terminating null
text[i]=(n-2)==i?'A':'\0'; // n-2 because, the count starts from zero
}
//Then print the null terminated string
printf("Filled string : %s\n",text); // You're all good :-)
Note: Use a tool like valgrind to find memory leaks & out of bound memory accesses.
The following code doesnt copy the contents of matches 2 to keys[0].
Why is that so?
char **keys;
char matches[2000];
char *matches2;
matches2 =strtok(matches," ");
strncpy(keys[0],matches2, sizeof keys[0]);
You forgot to allocate space for keys to point to, as well as space for keys[#] to point to.
Also, are you really sure you want to use strncpy? It does not guarantee 0-termination, instead copying at most n byte of the ggiven string and 0-filling the rest of the buffer.
The size for a string is the number of elements including 0-terminator: strlen(s)+1
For creating a copy of a string, you might look into non-standard strdup, a possible implementation:
char* strdup(const char* s) {
size_t n = strlen(s)+1;
char* r = malloc(n);
if(r)
memcpy(r, s, n);
return r;
}
Try this assuming that you already have allocated space for keys[0]
strncpy(keys[0], matches2, /*your desired size*/);
or
strcpy(keys[0], matches2);
I am writing a function which expands the string, str1 and stores it as str2. By expansion, I mean if str1 has "a-d", it should be stored in str2 as "abcd". I have written the following code. I get a debug error that stack around the variable str1 is corrupted.
Can someone please point out what's going wrong?
Thanks.
#include <stdio.h>
void expand(char s1[], char s2[]);
int main() {
char s1[] = "Talha-z";
char s2[] = "";
expand(s1, s2);
printf(s2);
}
void expand(char s1[], char s2[]) {
int i = 0;
int j= 0;
int k, c_next;
while ( s1[i] != '\0') {
switch (s1[i]) {
case ('-') :
c_next = s1[i+1];
for ( k = 1; k < c_next; k++) {
s2[j] = s1[i] + k;
j++;
}
break;
}
i++;
j++;
}
s2[j] = '\0';
}
You are not allocating sufficient memory for your target string (s2). But you are attempting to write to it, which means you will be writing into memory that you don't own, causing the corruption.
You will need to use dynamic allocation for s2 (i.e. by using malloc), but you will first need to calculate how much memory you need.
char s2[] = "";
This is equivalent to writing
char s2[1] = { '\0' };
It cannot hold more than a single character (or none at all, if the NUL terminator is required).
The problem is that when you initialize s2, you give it enough room for 1 character (i.e. the null terminating '\0'). Thus when you write into s2:
s2[j] = ...
there are no guarantees about what memory you're writing into.
To allocate memory for s2 dynamically, you need to use malloc. In other words, you need to figure out how much memory is required (i.e. by finding the length of the expanded string) and then give s2 that much memory, and finally fill it in via the procedure you have written.
The string s2 at present is on the stack for local variables for main() and is allocated only one byte for one character. When you call the function, it gets passed stack addresses for s1 and s2. The code is over-writing whatever is next to s2 on the stack of function main(). Hence, the error. Please use dynamic memory allocation as already suggested by Mr. Oli above.
Hope my explanation helps you.