i just started to learn how to program and i encountered this error that goes like this: "initialization makes integer from pointer without a cast [enabled by default]"
What is the problem?
// This program pairs three kids with their favorite superhero
#include <stdio.h>
#include <string.h>
main()
{
char Kid1[12];
// Kid1 can hold an 11-character name
// Kid2 will be 7 characters (Maddie plus null 0)
char Kid2[] = "Maddie";
// Kid3 is also 7 characters, but specifically defined
char Kid3[7] = "Andrew";
// Hero1 will be 7 characters (adding null 0!)
char Hero1 = "Batman";
// Hero2 will have extra room just in case
char Hero2[34] = "Spiderman";
char Hero3[25];
Kid1[0] = 'K'; //Kid1 is being defined character-by-character
Kid1[1] = 'a'; //Not efficient, but it does work
Kid1[2] = 't';
Kid1[3] = 'i';
Kid1[4] = 'e';
Kid1[5] = '\0'; // Never forget the null 0 so C knows when the
// string ends
strcpy(Hero3, "The Incredible Hulk");
printf("%s\'s favorite hero is %s.\n", Kid1, Hero1);
printf("%s\'s favorite hero is %s.\n", Kid2, Hero2);
printf("%s\'s favorite hero is %s.\n", Kid3, Hero3);
return 0;
}
The problem is with char Hero1 = "Batman":
When you use a double-quoted string of characters in your code, the compiler replaces it with a pointer to the beginning of the memory space in which the string will reside during runtime.
So by char Hero1 = "Batman", you are actually attempting to assign a memory address (which typically consists of 32 or 64 bits of data, depending on your system) into a character variable (which typically stores 8 bits of data).
In order to fix the problem, you need to change it to either one of the following options:
char Hero1[] = "Batman"
char* Hero1 = "Batman"
FYI, in both cases above, the string "Batman" will reside in a read-only memory section during runtime.
However, there is a notable difference between these two cases:
Using char Hero1[], the "Batman" string will be copied into the stack every time the function is called. The Hero1 array will start at that address, and you will be able to change the contents of that array at a later point within the function.
Using char* Hero1, the "Batman" string will not be copied into the stack every time the function is called. The Hero1 variable will be pointing to the original address of the string, hence you will not will be able to change the contents of that string at any point within the function.
When the executable image is generated from your code, the string is placed in the code-section, which is one of several memory-sections within the program. The compiler then replaces the so-called "string assignment" with a so-called "integer assignment".
For example, char* x = "abc" is changed into char* x = (char*)0x82004000 before being compiled into object code, where 0x82004000 is the (constant) address of the string in the program's memory space.
When you do sizeof("abc"), the executable image will not even contain the "abc" string, since there is no "runtime" operation performed on this string.
There is no object code generated for sizeof - the compiler computes this value during compilation, and immediately replaces it with a constant.
You can look into the (intermediate) map file that is usually generated, and see that the input string of that sizeof operation does not appear anywhere.
char Hero1 = "Batman";
should be
char Hero1[] = "Batman";
A couple times you have some issues:
#include <stdio.h>
#include <string.h>
main()
{
char Kid1[12];
// Kid1 can hold an 11-character name
// Kid2 will be 7 characters (Maddie plus null 0)
char Kid2[] = "Maddie";
// Kid3 is also 7 characters, but specifically defined
char Kid3[7] = "Andrew";
// Hero1 will be 7 characters (adding null 0!)
char *Hero1 = "Batman"; //needs to be a pointer
// Hero2 will have extra room just in case
char *Hero2 = "Spiderman"; //needs to be a pointer
char Hero3[25]
Kid1[0] = 'K'; //Kid1 is being defined character-by-character
Kid1[1] = 'a'; //Not efficient, but it does work
Kid1[2] = 't';
Kid1[3] = 'i';
Kid1[4] = 'e';
Kid1[5] = '\0'; // Never forget the null 0 so C knows when the
// string ends
strcpy(Hero3, "The Incredible Hulk");
printf("%s\'s favorite hero is %s.\n", Kid1, Hero1);
printf("%s\'s favorite hero is %s.\n", Kid2, Hero2);
printf("%s\'s favorite hero is %s.\n", Kid3, Hero3);
return 0;
}
You should define all of your vars at the top of the function, its a good C practice.
Other than that, I flagged the issues (and corrected them) with comments.
Solution:
This error you get because String data type is not in C
programming you can print string by using array or char pointer like
1.Array:
#include<stdio.h>
int main(){
char a[]={'a','b','c','d','f','\0'};
printf("%s",a);
return 0;
}
Click here to check the output of solution array
2.char pointer:
#include<stdio.h>
int main(){
char* a="abcd";
printf("%s",a);
return 0;
}
Click here to check the output of solution char pointer
Related
I am getting a string from the user and storing it in a variable plaintext, and then I want to convert that string to lowercase in a for loop and store it in a separate variable plaintextLowercase. However, when I change a character in the plaintextLowercase variable to lowercase, the same happens in the plaintext variable, which I want to remain unchanged. My code is below.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
// get_string() is a function defined in the header file cs50.h that prompts the user for string input and returns that string input
string plaintext = get_string("plaintext: ");
string plaintextLowercase = plaintext;
//this converts the entire string to lowercase, but the issue is it is doing the same to the 'plaintext' variable as well
//I only want the 'plaintextLowercase' string to be lowercase, while the 'plaintext' variable
for (int i = 0, n = strlen(plaintext); i < n; i++)
{
plaintextLowercase[i] = tolower(plaintextLowercase[i]);
}
printf("%s\n", plaintext);
printf("%s\n", plaintextLowercase);
}
You are using a library that obfuscates basic C concepts behind useless typedefs and macros. If you are working with strings in C, then char * is the only right way to do it. Avoid using something else, specially if you are still learning how the language works. If your book/library/course is suggesting you to use opaque data types like CS50's string, then throw it away and go find something else to study on.
What is happening here is that your cs50.h header defines string as:
typedef char * string;
Therefore, you are wrongly given the impression that doing:
string a = "123";
string b = a;
Will somehow magically create a copy of the string. This is not the case, as the code is equivalent to:
char *a = "123";
char *b = a;
Both a and b are pointers, and will simply end up pointing to the same constant string literal in memory. No copy happens.
This is the same with the result of the get_string() function, which dynamically allocates a string for you with malloc() under the hood. So this piece of code:
string plaintext = get_string("plaintext: ");
string plaintextLowercase = plaintext;
has the same "issue". Your lowercase and plaintextLowercase are just two pointers to the same memory area, containing the same string. If you want to copy the string, you can use strdup():
string plaintext = get_string("plaintext: ");
string plaintextLowercase = strdup(plaintext);
And of course, since the new string is also dynamically allocated, do not forget to free() it when you don't need it anymore:
free(plaintextLowercase);
The string allocated by get_string() is automatically deallocated for you at exit by the library (yet another counter-intuitive CS50 thing).
I'm having trouble when I try to store the stdin in a program inside char array variable.
It throws a segfault when it goes by these lines:
procNames[processNumber] = argv[1];
and
strcpy(procNames[processNumber], proc[0]);
How can I store the chars in the array procNames?
The usage is:
(stdin) <CHAR>: <NUMBER>
I want to store every <CHAR> and every <NUMBER> introduced by order. The <NUMBER> stores without erros, the <CHAR> storage throws the segmentation fault.
char line[80],proc[80];
// Storing
char procNames[80];
int procPorts[80];
// To iterate
int processNumber = 0;
int actualProcessNumber = 0;
[...]
for(;fgets(line,80,stdin);) {
sscanf(line,"%[^:]: %d",proc,&port);
[...]
if(strcmp(proc,argv[1]) == 0) {
if (repeatedProc == false) {
procNames[processNumber] = argv[1];
procPorts[processNumber] = puerto_udp;
actualProcessNumber = processNumber;
processNumber++;
}
} else {
if (repeatedProc == false) {
strcpy(procNames[processNumber], proc[0]);
procPorts[processNumber] = port;
processNumber++;
}
}
}
Can someone please help me?
Regarding the issues you get:
1.
You need
char procNames[N][80];
instead of
char procNames[80];
where N gives the amount of strings to hold in procNames. [80] - 1 just specifies the maximum amount of characters possible in each string.
2.
You cannot assign arrays with strings by the = operator in C. Use strcpy() instead.
Replace
procNames[processNumber] = argv[1];
with
strcpy( procNames[processNumber], argv[1] );
3.
strcpy(procNames[processNumber], proc[0]);
The second argument of needs to be a pointer to char, proc[0] is of type char. Use proc only.
proc has no string in it to copy. Use at least char proc[80] = ""; to not get a runtime error.
Your procNames is an array of characters, not an array of pointers. Arrays cannot be assigned, just copied, and procNames[processNumber] = argv[1] should actually issue a warning / an error.
Further, as you intend to have an array of - let's say - 10 such names, you probably mean
char procNames[10][80];
Then you can write
strcpy(procNames[processNumber],argv[1]);
to copy the contents of the string argv[1] points to.
Furhter, in order to avoid that you exceed the length of a procNames-entry, I suggest to use
strncpy(procNames[processNumber],argv[1],80);
You defined char procNames[80]; which means it's a string that can hold 80 characters (also counting the 0-terminator at the end).
Later one you're doing this procNames[processNumber] = argv[1]; where procNames[processNumber] points to a character and argv[1] is a string holding the first command line parameter. So in fact you're trying to assign a pointer to a char.
Your compiler must have at least warned you about this.
Make sure to really look at compiler output as it often tries to tell you what you are doing wrong.
I know the C language has dynamic length strings whereby it uses the special character null (represented as 0) to terminate a string - rather than maintaining the length.
I have this simple C code that creates a string with the null character in the fifth index:
#include <stdio.h>
#include <stdlib.h>
int main () {
char * s= "sdfsd\0sfdfsd";
printf("%s",s);
s[5]='3';
printf("%s",s);
return 0;
}
Thus, a print of the string will only output up to the fifth index. Then the code changes the character at the fifth index to a '3'. Given my understanding, I assumed it would print the full string with the 3 instead of the null, as such:
sdfsdsdfsd3sfdfsd
but instead it outputs:
sdfsdsdfsd
Can someone explain this?
This program exhibits undefined behavior because you modify a read-only string literal. char* s = "..." makes s point to constant memory; C++ actually disallows pointing non-const char* to string literals, but in C it's still possible, and we have to be careful (see this SO answer for more details and a C99 standards quote)
Change the assignment line to:
char s[] = "sdfsd\0sfdfsd";
Which creates an array on the stack and copies the string to it, as an initializer. In this case modifying s[5] is valid and you get the result you expect.
String literals can not be changed because the compiler put the string literals into a read-only data-section (but this might vary by underlying platform). The effect of attempting to modify a string literal is undefined.
In your code:
char * s= "sdfsd\0sfdfsd"
Here, s is char pointer pointing to a string "sdfsd\0sfdfsd" stored in read-only memory, making it immutable.
Here you are trying to modify the content of read-only memory:
s[5]='3';
which leads to undefined behavior.
Instead, you can use char[]:
#include <stdio.h>
int main () {
char a[] = "sdfsd\0sfdfsd";
char * s = a;
printf("%s",s);
s[5]='3';
printf("%s\n",s);
return 0;
}
This operation has failed:
s[5] = 3;
You're trying to change a string literal, which is always read-only. My testing shows the program exited with segfault:
Segmentation fault (core dumped)
You should store it in an array (or allocated memory) before any attempts to change it:
char s[] = "sdfsd\0sfdfsd";
With the above change, the program works as intended.
#include <stdio.h>
int main(){
char x[10] = "aa\0a";
x[2] = '1';
puts(x);
printf("\n\n\nPress any key to exit...");
getch();
return 0;
}
Output: aa1a
Apologies if my following question sounds trivial but I'm struggling with the fundamental concept of "converting an a char array to a string" for use in the method strstr().
Essentially I have an array called EUI_only[] which is dynamically populated at a certain stage of my program i.e.
EUI_only[0] = A;
EUI_only[1] = B;
EUI_only[2] = C;
EUI_only[3] = D;
EUI_only[4] = E;
I declared EUI_only as follows at the top of my program:
char EUI_only[];
I can confirm that EUI_only[] is successfully populated as justbefore I use it in method strstr() I print it out.
Now I have the second array called receive_key_press_temporary_analysis_buffer which I intend on utilising in my strstr() i.e. the array which contains characters similar to those in EUI_only.
This array is also dynamically populated in a certain point of my program and I can confirm that the contents of the array are intact just before I use it in strstr() as I've printed this array.
Content of this array called receive_key_press_temporary_analysis_buffer can be seen below:
receive_key_press_temporary_analysis_buffer[0] = 1;
receive_key_press_temporary_analysis_buffer[1] = 2;
receive_key_press_temporary_analysis_buffer[2] = C;
receive_key_press_temporary_analysis_buffer[3] = A;
receive_key_press_temporary_analysis_buffer[4] = B;
receive_key_press_temporary_analysis_buffer[5] = C;
receive_key_press_temporary_analysis_buffer[6] = D;
receive_key_press_temporary_analysis_buffer[7] = E;
receive_key_press_temporary_analysis_buffer[8] = 3;
receive_key_press_temporary_analysis_buffer[9] = 4;
Below essentially is how I use both arrays in strstr():
char* is_eui_only_content_in_receive_key_press_analysis = strstr(receive_key_press_temporary_analysis_buffer, EUI_only);
printf("\n\rResult of is_eui_only_content_in_receive_key_press_analysis: %s\n\r", is_eui_only_content_in_receive_key_press_analysis);
Basically when I print the outcome of strstr() it gives me:
Result of is_eui_only_content_in_receive_key_press_analysis: CDE34
On the other hand if I reinitialise my EUI_only follows:
EUI_only[] = "ABCDE";
Essentially I get the expected result from the strstr() i.e.
Result of is_eui_only_content_in_receive_key_press_analysis: ABCDE34
Why could it be the strstr() doesn't give me my expected result when I utilise my dynamically populated EUI_only[] array?
Thanks,
Alex.
If your only definition is char EUI_only[]; then it actually has a size of 1. You cause a buffer overflow by writing 5 characters to it. In C, arrays don't automatically resize; they have a fixed size for their lifetime.
Successfully printing its contents doesn't prove anything, as it could perhaps happen that you write into memory you don't own, but nothing disturbs that memory in between the write and the read.
Secondly, the str functions expect a string. The definition of a string is a series of characters followed by a null character. In your example code you do not have the null character, so even if you did not have the allocation problem, you don't actually have a string; therefore the function misbehaves.
When you write char EUI_only[] = "ABCDE"; , it is doing char EUI_only[6] = { 'A', 'B', 'C', 'D', 'E', 0 }; which is a string, so everything works as expected.
Update: The reason the array size would be 1 is covered by C99 6.9.2, "tentative definitions". After the line char EUI_only[];, EUI_only has incomplete type. For an incomplete array type, you can dereference it, but you can't do sizeof on it. You may complete the type at any point later on in the source file; and if you don't, then it behaves as if the last line of the source file was char EUI_only[] = { 0 };. This is a rarely-used feature of C; usually you would declare a complete type by either specifying the size, or providing an initializer.
C strings are terminated by null '\0' character
EUI_only[5] = '\0' ;
and
receive_key_press_temporary_analysis_buffer[10] = '\0' ;
Make sure you have extra space for null character at declaration.
When I do this
char *paths[10];
paths[0] = "123456";
printf(1,"%s\n",paths[0]);
printf(1,"%c\n",paths[0][2]);
Output:
123456
3
But when I you do this
char *paths[10];
paths[0][0]='1';
paths[0][1]='2';
paths[0][2]='3';
paths[0][3]='4';
paths[0][4]='5';
paths[0][5]='6';
printf(1,"%s\n",paths[0]);
printf(1,"%c\n",paths[0][2]);
Output:
(null)
3
Why it is null in this case?
How to create a string array using characters in C? I am a bit new to C and feeling some difficulties to program in C
You have a lot of options provided by various answers, I'm just adding a few points.
You can create a string array as follows:
I. You can create an array of read only strings as follows:
char *string_array0[] = {"Hello", "World", "!" };
This will create array of 3 read-only strings. You cannot modify the characters of the string in this case i.e. string_array0[0][0]='R'; is illegal.
II. You can declare array of pointers & use them as you need.
char *string_array1[2]; /* Array of pointers */
string_array1[0] = "Hey there"; /* This creates a read-only string */
/* string_array1[0][0] = 'R';*/ /* This is illegal, don't do this */
string_array1[1] = malloc(3); /* Allocate memory for 2 character string + 1 NULL char*/
if(NULL == string_array1[1])
{
/* Handle memory allocation failure*/
}
string_array1[1][0] = 'H';
string_array1[1][1] = 'i';
string_array1[1][2] = '\0'; /* This is important. You can use 0 or NULL as well*/
...
/* Use string_array1*/
...
free(string_array1[1]); /* Don't forget to free memory after usage */
III. You can declare a two dimensional character array.
char string_array2[2][4]; /* 2 strings of atmost 3 characters can be stored */
string_array2[0][0] = 'O';
string_array2[0][1] = 'l';
string_array2[0][2] = 'a';
string_array2[0][3] = '\0';
string_array2[1][0] = 'H';
string_array2[1][1] = 'i';
string_array2[1][2] = '\0'; /* NUL terminated, thus string of length of 2 */
IV. You can use pointer to pointer.
char ** string_array3;
int i;
string_array3 = malloc(2*sizeof(char*)); /* 2 strings */
if(NULL == string_array3)
{
/* Memory allocation failure handling*/
}
for( i = 0; i < 2; i++ )
{
string_array3[i] = malloc(3); /* String can hold at most 2 characters */
if(NULL == string_array3[i])
{
/* Memory allocation failure handling*/
}
}
strcpy(string_array3[0], "Hi");
string_array3[1][0]='I';
string_array3[1][1]='T';
string_array3[1][2]='\0';
/*Use string_array3*/
for( i = 0; i < 2; i++ )
{
free(string_array3[i]);
}
free(string_array3);
Points to remember:
If you are creating read-only string, you cannot change the character
in the string.
If you are filling the character array, make sure you have
memory to accommodate NUL character & make sure you terminate your
string data with NUL character.
If you are using pointers &
allocating memory, make sure you check if memory allocation is done
correctly & free the memory after use.
Use string functions from
string.h for string manipulation.
Hope this helps!
P.S.: printf(1,"%s\n",paths[0]); looks shady
char *paths[10];
paths[0][0]='1';
paths is an array of pointers. paths is not initialized to anything. So, it has garbage values. You need to use allocate memory using malloc. You just got unlucky that this program actually worked silently. Think of what address location would paths[0][0] would yield to assign 1 to it.
On the other hand, this worked because -
char *paths[10];
paths[0] = "123456";
"123456" is a string literal residing in the reading only location. So, it returns the starting address of that location which paths[0] is holding. To declare correctly -
const char* paths[10];
paths is an array of 10 pointers to char. However, the initial elements are pointers which can not be dereferenced. These are either wild (for an array in a function) or NULL for a static array. A wild pointer is an uninitialized one.
I would guess yours is static, since paths[0] is NULL. However, it could be a coincidence.
When you dereference a NULL or uninitialized pointer, you're reading or writing to memory you don't own. This causes undefined behavior, which can include crashing your program.
You're actually lucky it doesn't crash. This is probably because the compiler sees you're writing a constant to paths[0][2], and changes your printf to print the constant directly. You can not rely on this.
If you want to have a pointer you're allowed to write to, do:
paths[0] = malloc(string_length + 1);
string_length is the number of characters you can write. The 1 gives you room for a NUL. When you're done, you have to free it.
For your second example, if you know the size of each string you can write e.g.
char paths[10][6];
paths[0][0]='1';
...
paths[0][5]='6';
This way you have 10 strings of length 6 (and use only the first string so far).
You can define the string yourself, right after
#inlcude <stdio.h>
like this
typedef char string[];
and in main you can do this
string paths = "123456";
printf("%s\n", paths);
return 0;
so your code would look like this
#include <stdio.h>
typedef char string[];
int main() {
string paths = "123456";
printf("%s", paths);
}