Note: I can't use any libs or includes!
I have the following Code:
void twstng(char * str, int end, int strt) {
if(strt != end && strt != end-1) {
int hlp = str[strt];
printf("strt %d end %d hlp %d\n", strt, end, hlp);
str[strt] = str[end-1];
printf("test\n");
str[end-1] = hlp;
printf("test\n");
twstng(str, strt+1, end-1);
}
}
and in the main function:
char * sol = "hello";
twisting(sol, 5, 0);
I want to twist the entire string. But the console shows:
strt 0 end 4 help 104
And then comes a memory access error. But why?
My second problem is, that in the original task the given string is a
const char * const str
How can I work with it in the twstng function?
Your char *sol is a pointer to the string "hello". Being a string literal, it is actually read-only, and thus when you pass the pointer to your function, you get an error when you modify the contents of the constant string "hello" through the pointer.
Regarding the second part of the question, const char * const (i.e., constant pointer to a constant char) would indeed be a better type for the pointer, as it would convey that the thing pointed to is constant. However, then you cannot pass this pointer to the function (because the function takes a pointer to a non-const char), and it is not clear from the information given how you are "allowed" to work around this. One way is to copy the string and modify the copy.
edit: And as pointed out by other answers, your recursive call mixes up the start and end arguments (by using the more logical order of start first).
In C all string literals are read-only arrays of characters. It can be stored in memory that is not modifiable, leading to errors such as your when you attempt to modify it. That's why you should always use const char * when referring to string literals.
Use an array instead:
char sol[] = "hello";
I believe the recursive call to 'twstng()' at the bottom of the function has passed the new start and end indexes in the wrong order, given the names in the declaration (or else the declaration has them in the wrong order).
You mixed up your arguments.
Your function declaration says, that the first argument is the end and the second is the strt.
Your recursive call mixes them up.
Related
I was doing some pointers and arrays practice in C and I noticed all my four methods returned the same answer.My question is are there disadvantages of using any one of my below methods? I am stunned at how all these four give me the same output. I just noticed you can use a pointer as if it was an array and you can also use an array as if it was a pointer?
char *name = "Madonah";
int i= 0;
for (i=0;i<7; i++){
printf("%c", *(name+i));
}
char name1 [7] = "Madonah";
printf("\n");
int j= 0;
for (j=0;j<7; j++){
printf("%c", name1[j]);
}
char *name2 = "Madonah";
printf("\n");
int k= 0;
for (k=0;k<7; k++){
printf("%c", name2[k]);
}
char name3 [7] = "Madonah";
printf("\n");
int m= 0;
for (m=0;m<7; m++){
printf("%c", *(name+m));
}
Results:
Madonah
Madonah
Madonah
Madonah
It is true that pointers and arrays are equivalent in some context, "equivalent" means neither that they are identical nor even interchangeable. Arrays are not pointers.
It is pointer arithmetic and array indexing that are equivalent, pointers and arrays are different.
which one is preferable and the advantages/Disadvantages?
It depends how you want to use them. If you do not wanna modify string then you can use
char *name = "Madonah";
It is basically equivalent to
char const *name = "Madonah";
*(name + i) and name[i] both are same. I prefer name[i] over *(name + i) as it is neat and used most frequently by C and C++ programmers.
If you like to modify the string then you can go with
char name1[] = "Madonah";
In C, a[b], b[a], *(a+b) are equivalent and there's no difference between these 3. So you only have 2 cases:
char *name = "Madonah"; /* case 1 */
and
char name3 [7] = "Madonah"; /* case 2 */
The former is a pointer which points to a string literal. The latter is an array of 7 characters.
which one is preferred depends on your usage of name3.
If you don't intend to modify then the string then you can use (1) and I would also make it const char* to make it clear and ensure the string literal is not modified accidentally. Modifying string literal is undefined behaviour in C
If you do need to modify it then (2) should be used as it's an array of characters that you can modify. One thing to note is that in case (2), you have explicitly specified the size of the array as 7. That means the character array name3 doesn't have a null terminator (\0) at the end. So it can't be used as a string. I would rather not specify the size of the array and let the compiler calculate it:
char name3 [] = "Madonah"; /* case 2 */
/* an array of 8 characters */
Just in addition to what others said, I will add an image for better illustration. If you have
char a[] = "hello";
char *p = "world";
What happens in first case enough memory is allocated for a (6 characters) on the stack usually, and the string "hello" is copied to memory which starts at a. Hence, you can modify this memory region.
In the second case "world" is allocated somewhere else(usually in read only region), and a pointer to that memory is returned which is simply stored in p. You can't modify the string literal in this case via p.
Here is how it looks:
But for your question stick to notation which is easier, I prefer [].
More info on relationship between arrays and pointers is here.
In all cases, in C pointer + index is the same as pointer[index]. Also, in C an array name used in an expression is treated as a pointer to the first element of the array. Things get a little more mystifying when you consider that addition is commutative, which makes index + pointer and index[pointer] legal also. Compilers will usually generate similar code no matter how you write it.
This allows cool things like "hello"[2] == 'l' and 2["hello"] == 'l'.
it is convenient to use array syntax for random access
int getvalue(int *a, size_t x){return a[x];}
and pointer arithmetic syntax for sequential access
void copy_string(char *dest, const char *src){while((*dest++=*src++));}
Many compilers can optimize sequential accesses to pointers better than using array indices.
For practicing pointer and array idioms in C, those are all valid code blocks and illustrative of the different ways of expressing the same thing.
For production code, you wouldn't use any of those; you would use something both easier for humans to read and more likely to be optimized by the compiler. You'd dispense with the loop entirely and just say:
printf("%s", name);
(Note that this requires name include the \0 character at the end of the string, upon which printf relies. Your name1 and name3 definitions, as written, do not allocate the necessary 8 bytes.)
If you were trying to do something tricky in your code that required one of the more verbose methods you posted, which method you chose would depend on exactly what tricky thing you were trying to do (which you would of course explain in code comments -- otherwise, you would look at your own code six months later and ask yourself, "What the heck was I doing here??"). In general, for plucking characters out of a string, name[i] is a more common idiom than *(name+i).
char name[] = "Madonah";
char* name = "Madonah";
When declared inside a function, the first option yields additional operations every time the function is called. This is because the contents of the string are copied from the RO data section into the stack every time the function is called.
In the second option, the compiler simply sets the variable to point to the address of that string in memory, which is constant throughout the execution of the program.
So unless you're planning to change the contents of the local array (not the original string - that one is read-only), you may opt for the second option.
Please note that all the details above are compiler-implementation dependent, and not dictated by the C-language standard.
can I know which one is easy to use [...]
Try sticking to use the indexing operator [].
One time your code gets more complex and you then notice that things are "more easy" to code using pointer arithmetical expressions.
This typically will be the case when you also start to use the address-of operator: &.
If for example you see your self in the need to code:
char s[] = "Modonah";
char * p = &s[2]; /* This gives you the address of the 'd'. */
you will soon notice that it's "easier" to write:
char * p = s + 2; /* This is the same as char * p = &s[2];. */
An array is just a variable that contains several values, each value has an index, you probably know that already.
Pointers are one of those things you dont need to know about until you realize you need to use them. Pointers are not variables themselves they are literally pointers to variables.
An example of how and why you might want to use a pointer.
You create a variable in one function which you want to use in another function.
You could pass your variable to the new function in the function header.
This effectively COPIES the values from the original variable to a new variable local to the new function. Changes made to it in the new function only change the new variable in the new function.
But what if you wanted changes made in the new function to change the original variable where it is in the first function ?
You use a pointer.
Instead of passing the actual variable to the new function, you pass a pointer to the variable. Now changes made to the variable in the new function are reflected in the original variable in the first function.
This is why in your own example using the pointer to the array and using the actual array while in the same function has identical results. Both of them are saying "change this array".
this is what I have so far but I can't figure out what is wrong with it
void newCopy(char *s)
{
char newString = malloc(sizeof(int * strlen(s)));
newString = s;
return &newString;
}
void newCopy(char *s)
{
char newString = malloc(sizeof(int * strlen(s)));
First and second problems are here.
First is, You're assigning the return of malloc, which is a pointer, to a variable declared as char. The variable should be declared as char*.
Second is, your input to sizeof is wrong.
int * strlen(s) is nonsense and won't compile, because you're trying to multiply a type and an integer. You meant sizeof(int) (which is an integer) * strlen(s) (also an integer) which will compile.
You should use sizeof(char) instead of sizeof(int), since it is a string.
You should add 1 to the size, since strings in C need to be null terminated by an extra \0 that strlen does not report being part of the string length.
Putting it all together, sizeof(char)*(strlen(s)+1)
newString = s;
Third problem is here. = is not a magic operator - it assigns the value in the variable s (which is a pointer) to the value in the variable newString (which after fixing the above mistake, will also be a pointer). It does nothing beside that.
What you want to do instead is use strcpy, which is a function that copies the contents of one string (by following its pointer) to the contents of another string (by following its pointer). http://www.cplusplus.com/reference/cstring/strcpy/
return &newString;
Fourth and fifth problems are here.
Fourth is, You have declared the function as void and here you are trying to return a char*.
Fifth is, you are trying to return a pointer to something that was declared on the stack (a local variable). As soon as the function returns, anything on the stack for that function is trash and cannot be referenced anymore.
However, if you correctly make newString of type char*, all you need to do is return newString; And you correctly return a pointer by value which points into the heap (thanks to the earlier malloc).
}
Finally, judging by this code, I should inform you that C is not a newbie friendly language, where you can just type things that 'look like' what you want to happen and pray it works. If you're even slightly wrong your code will crash and you will have zero idea why, because you don't know the right way to do things. Either read a really good book on C and teach yourself everything from basic to advance step by step so you know how it all works, or pick up a more user friendly language.
I should start by pointing out that in my opinion, given the number and (especially) nature of the mistakes in this code, you probably need to get a good book on C.
Your newString = s; overwrites the pointer instead of copying the string into the space you just allocated. Thus, you lose the pointer to what you just allocating (leaking the memory) without making a copy. You probably want to use strcpy instead of direct assignment.
Your computation of the size you allocate isn't what you really want either. Typically, for a string of length N, you want to allocate N+1 bytes. You're currently attempting to allocat sizeof(int * strlen(s)) bytes, which shouldn't even compile.
A corrected version should be like:
char *newCopy(char *s)
{
if (s == NULL)
return NULL;
char *newString = malloc(strlen(s) + 1);
if (newString == NULL)
return NULL;
strcpy(newString, s);
return newString;
}
I was trying to concatenate 2 strings without using strcat, but I am getting a runtime error. Please, someone help me out here...
Also, is this statement q=q+len; correct? Can we add a variable to a pointer??
#include<stdio.h>
#include<string.h>
void xstrcat(char*,char*);
int main()
{
char source[]="folks";
char target[30]="hello";
xstrcat(target,source);
printf("%s",source);
printf("%s",target);
return 0;
}
void xstrcat(char*p,char*q)
{
int len=0;
len=strlen(q);
q=q+len;
while(*p!='\0')
{
*q=*p;
q++;
p++;
}
*q='\0';
}
Some mistakes in your implementation:
1 - You are accessing random memory. Once you don't have a /0 in your string.
while(*p!='/0')
must be:
while(*p!='\0')
Note the slash \.
2 - You are overwriting random memory when try to add *p into *q. You must create a new variable with enough space for store them.
Also, is this statement q=q+len; correct? Can we add a variable to a
pointer??
Yes. It's a pointer arithmetic expression.
You are passing target as the first parameter in function call, but it seems that the function tries to use the second parameter as the target. So, maybe you would just need yo switch places of parameters in the function call.
Another thing is that you are using slash instead of backslash when escaping the null character. So, change '/0' to '\0'.
Regarding adding int to pointer: in your case in the function that type of pointer arithmetic is perfectly legal.
There are a few things, first, you need to check against \0 and not /0
while(*p!='\0')
But also, you are trying to add a string to a string literal, which will cause undefined behaviour. Switch
xstrcat(target,source);
to
xstrcat(source, target);
Finally, the last line in xstrcat should be changed to
*q='\0';
you are overwriting the memory.
You are concatenating to source which does not have enough memory to hold concatenated characters.
You may want to reverse definition of source and target.
i.e.
char source[30] = "folks";
char *target = "hello";
Or
call xstrcat as xstrcat(source, target);
The problem lies in your code in the below line:
xstrcat(target,source);
It should be
xstrcat(source,target);
or in your xstrcat function, try considering the first parameter as target and second as source.
I'm really new to C and all I know is that the error is related to oldname and newname not be initialized
#include <stdio.h>
int main (int argc, char const *argv[])
{
int result;
int lengthOne;
int lengthTwo;
lengthOne = sizeof(argv[0]);
lengthTwo= sizeof(argv[1]);
char oldname[lengthOne] = argv[0];
char newname[lengthOne] = argv[1];
result = rename(oldname, newname);
if (result == 0) {
puts "File renamed";
} else {
perror "ERROR: Could not rename file";
}
return 0;
}
app.c: In function ‘main’:
app.c:11: error: variable-sized object may not be initialized
app.c:12: error: variable-sized object may not be initialized
app.c:17: error: expected ‘;’ before string constant
app.c:19: error: expected ‘;’ before string constant
lengthOne = sizeof(argv[0]);
lengthTwo= sizeof(argv[1]);
This gives you the size of a char*, not the length of the string. You meant strlen, not sizeof.
char oldname[lengthOne] = argv[0];
char newname[lengthOne] = argv[1];
You can't assign to arrays like that. You could strcpy them, but it's unnecessary here because you can just use pointers.
const char* oldname = argv[0];
const char* newname = argv[1]; // But verify that argc >= 2 first!
EDIT: Also, don't forget that argv[0] is the name of the program itself, and argv[1] is the first argument. If your intent was to write a mv-like program instead of a program that renames itself, you want argv[1] and argv[2].
You seem to not be understanding what pointers are in C. This is a very core concept that you need to understand to be able to use the language.
I would start with a tutorial on them. A guick google brings this up as the first result: http://pw1.netcom.com/~tjensen/ptr/pointers.htm
First, char x[length] = /* something */; only works for string literals (i.e. "string" or {'s', 't', 'r', 'i', 'n', 'g', '\0'} if you want to be masochistic).
Second, to call a function, use parenthesis. puts("Text"); and printf("Text\n");. They are not optional like they are in some languages.
Third, as a function parameter (even if it's a parameter to main()), an array type decays to a pointer. So your function signature is effectively int main(int argc, char **argv) (and I prefer to write it that way, personally, but it makes no difference). You can't take the sizeof an array that has decayed to a pointer because it's not an array anymore and has no associated information about it's size. To get the size, use strlen().
Fourth, use a size_t to store sizes. Using an int to store sizes is wrong - there's no guarantee that int is large enough to hold sizes, and you can't have a -5 sized object of any kind. size_t is an unsigned integral type included in the standard for precisely this purpose.
Lastly, if you need a object whose size depends on runtime conditions, you can't use an array. You have to use a pointer, and use malloc to create a block of memory of the correct size, and then use free to destroy it when you're done. EDIT: Or just assign argv[0] to the pointer. argv is guaranteed in the standard to be writable, so you can edit it (just try to avoid appending anything).
sizeof is a compile-time check... the sizeof any argv element will be the number of bytes in a pointer-to-char. It has nothing to do with the run-time length of the text that pointer may address: strlen() returns that. But, C doesn't let you create dynamically (i.e. runtime) sized arrays. And even then you can't copy a string into another string with =... it requires a call to strcpy(dest, src). To make it work, obviously the easiest thing is:
result = rename(argv[0], argv[1])
But, I appreciate you're trying to learn how to copy the values into your own buffer. To do so, you need to dynamically create a sufficiently large buffer (memory-allocate or malloc), string-copy it, use it then free it. Several of these requirements are satisfied by the strdup() function:
const char* p_old_name = strdup(argv[0]);
const char* p_new_name = strdup(argv[1]);
rename(p_old_name, p_new_name);
free(p_old_name);
free(p_new_name);
Alternatively, you can statically specify a maximum size for the two strings (dangerous if you get it wrong - strncpy() can provide a more safety but a mistake may still prevent your program working with some long-but-valid paths):
#include <linux/limit.h> // or wherever you can find PATH_MAX or similar
...
char old_name[PATH_MAX];
char new_name[PATH_MAX];
strcpy(old_name, argv[0]);
strcpy(new_name, argv[1]);
rename(old_name, new_name);
Note: as argv[0] is the program name, this program changes it's own executable name to whatever the second argument is. If you want it to change another file's name, then you should use argv[0] and argv[1].
sizeof() returns the size of the type - ie the size of a pointer (probably 32bits) or a char (8bits)
To get the length of a string you need strlen()
Additionally in ansi C you can't create an array with a variable for the size. You can in the new C standard or for now you can use malloc() to create an array
argv is of the type char*[], i.e., an array of pointers to char. Thus, any first level element will simply be a char* and, as such, sizeof(argv[i]) will always return the native pointer size. You need to use strlen or some equivalent function to get the length of the string.
I've seen people's code as:
char *str = NULL;
and I've seen this is as well,
char *str;
I'm wonder, what is the proper way of initializing a string? and when are you supposed to initialize a string w/ and w/out NULL?
You're supposed to set it before using it. That's the only rule you have to follow to avoid undefined behaviour. Whether you initialise it at creation time or assign to it just before using it is not relevant.
Personally speaking, I prefer to never have variables set to unknown values myself so I'll usually do the first one unless it's set in close proximity (within a few lines).
In fact, with C99, where you don't have to declare locals at the tops of blocks any more, I'll generally defer creating it until it's needed, at which point it can be initialised as well.
Note that variables are given default values under certain circumstances (for example, if they're static storage duration such as being declared at file level, outside any function).
Local variables do not have this guarantee. So, if your second declaration above (char *str;) is inside a function, it may have rubbish in it and attempting to use it will invoke the afore-mentioned, dreaded, undefined behaviour.
The relevant part of the C99 standard 6.7.8/10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:
if it has pointer type, it is initialized to a null pointer;
if it has arithmetic type, it is initialized to (positive or unsigned) zero;
if it is an aggregate, every member is initialized (recursively) according to these rules;
if it is a union, the first named member is initialized (recursively) according to these rules.
I'm wonder, what is the proper way of initializing a string?
Well, since the second snippet defines an uninitialized pointer to string, I'd say the first one. :)
In general, if you want to play it safe, it's good to initialize to NULL all pointers; in this way, it's easy to spot problems derived from uninitialized pointers, since dereferencing a NULL pointer will yield a crash (actually, as far as the standard is concerned, it's undefined behavior, but on every machine I've seen it's a crash).
However, you should not confuse a NULL pointer to string with an empty string: a NULL pointer to string means that that pointer points to nothing, while an empty string is a "real", zero-length string (i.e. it contains just a NUL character).
char * str=NULL; /* NULL pointer to string - there's no string, just a pointer */
const char * str2 = ""; /* Pointer to a constant empty string */
char str3[] = "random text to reach 15 characters ;)"; /* String allocated (presumably on the stack) that contains some text */
*str3 = 0; /* str3 is emptied by putting a NUL in first position */
this is a general question about c variables not just char ptrs.
It is considered best practice to initialize a variable at the point of declaration. ie
char *str = NULL;
is a Good Thing. THis way you never have variables with unknown values. For example if later in your code you do
if(str != NULL)
doBar(str);
What will happen. str is in an unknown (and almost certainly not NULL) state
Note that static variables will be initialized to zero / NULL for you. Its not clear from the question if you are asking about locals or statics
Global variables are initialized with default values by a compiler, but local variables must be initialized.
an unitialized pointer should be considered as undefined so to avoid generating errors by using an undefined value it's always better to use
char *str = NULL;
also because
char *str;
this will be just an unallocated pointer to somewhere that will mostly cause problems when used if you forget to allocate it, you will need to allocate it ANYWAY (or copy another pointer).
This means that you can choose:
if you know that you will allocate it shortly after its declaration you can avoid setting it as NULL (this is a sort of rule to thumb)
in any other case, if you want to be sure, just do it. The only real problem occurs if you try to use it without having initialized it.
It depends entirely on how you're going to use it. In the following, it makes more sense not to initialize the variable:
int count;
while ((count = function()) > 0)
{
}
Don't initialise all your pointer variables to NULL on declaration "just in case".
The compiler will warn you if you try to use a pointer variable that has not been initialised, except when you pass it by address to a function (and you usually do that in order to give it a value).
Initialising a pointer to NULL is not the same as initialising it to a sensible value, and initialising it to NULL just disables the compiler's ability to tell you that you haven't initialised it to a sensible value.
Only initialise pointers to NULL on declaration if you get a compiler warning if you don't, or you are passing them by address to a function that expects them to be NULL.
If you can't see both the declaration of a pointer variable and the point at which it is first given a value in the same screen-full, your function is too big.
static const char str[] = "str";
or
static char str[] = "str";
Because free() doesn't do anything if you pass it a NULL value you can simplify your program like this:
char *str = NULL;
if ( somethingorother() )
{
str = malloc ( 100 );
if ( NULL == str )
goto error;
}
...
error:
cleanup();
free ( str );
If for some reason somethingorother() returns 0, if you haven't initialized str you will
free some random address anywhere possibly causing a failure.
I apologize for the use of goto, I know some finds it offensive. :)
Your first snippet is a variable definition with initialization; the second snippet is a variable definition without initialization.
The proper way to initialize a string is to provide an initializer when you define it. Initializing it to NULL or something else depends on what you want to do with it.
Also be aware of what you call "string". C has no such type: usually "string" in a C context means "array of [some number of] char". You have pointers to char in the snippets above.
Assume you have a program that wants the username in argv[1] and copies it to the string "name". When you define the name variable you can keep it uninitialized, or initialize it to NULL (if it's a pointer to char), or initialize with a default name.
int main(int argc, char **argv) {
char name_uninit[100];
char *name_ptr = NULL;
char name_default[100] = "anonymous";
if (argc > 1) {
strcpy(name_uninit, argv[1]); /* beware buffer overflow */
name_ptr = argv[1];
strcpy(name_default, argv[1]); /* beware buffer overflow */
}
/* ... */
/* name_uninit may be unusable (and untestable) if there were no command line parameters */
/* name_ptr may be NULL, but you can test for NULL */
/* name_default is a definite name */
}
By proper you mean bug free? well, it depends on the situation. But there are some rules of thumb I can recommend.
Firstly, note that strings in C are not like strings in other languages.
They are pointers to a block of characters. The end of which is terminated with a 0 byte or NULL terminator. hence null terminated string.
So for example, if you're going to do something like this:
char* str;
gets(str);
or interact with str in any way, then it's a monumental bug. The reason is because as I have just said, in C strings are not strings like other languages. They are just pointers. char* str is the size of a pointer and will always be.
Therefore, what you need to do is allocate some memory to hold a string.
/* this allocates 100 characters for a string
(including the null), remember to free it with free() */
char* str = (char*)malloc(100);
str[0] = 0;
/* so does this, automatically freed when it goes out of scope */
char str[100] = "";
However, sometimes all you need is a pointer.
e.g.
/* This declares the string (not intialized) */
char* str;
/* use the string from earlier and assign the allocated/copied
buffer to our variable */
str = strdup(other_string);
In general, it really depends on how you expect to use the string pointer.
My recommendation is to either use the fixed size array form if you're only going to be using it in the scope of that function and the string is relatively small. Or initialize it to NULL. Then you can explicitly test for NULL string which is useful when it's passed into a function.
Beware that using the array form can also be a problem if you use a function that simply checks for NULL as to where the end of the string is. e.g. strcpy or strcat functions don't care how big your buffer is. Therefore consider using an alternative like BSD's strlcpy & strlcat. Or strcpy_s & strcat_s (windows).
Many functions expect you to pass in a proper address as well. So again, be aware that
char* str = NULL;
strcmp(str, "Hello World");
will crash big time because strcmp doesn't like having NULL passed in.
You have tagged this as C, but if anyone is using C++ and reads this question then switch to using std::string where possible and use the .c_str() member function on the string where you need to interact with an API that requires a standard null terminated c string.