how to set char array to string in c - c

so i have a struct call Process_Info
struct Process_Info {
char name[128];
int pid;
int parent_pid;
int priority;
int status;
};
and an array of Process_Info call info. I set pid in info to an integer, it works but when I try to set name in info to "{kernel}" like this
info[i].name="{kernel}";
and it give me incompatible type in assignment error. I search online it seem i can do this, like in http://www.cs.bu.edu/teaching/cpp/string/array-vs-ptr/, they did char label[] = "Single"; So what am i doing wrong?

The short answer: A C compiler will bake constant strings into the binary, so you need to use strncpy (or strcpy if you aren't worried about security) to copy "{kernel}" into info[i].name.
The longer answer: Whenever you write
char label[] = "Single";
the C compiler will bake the string "Single" into the binary it produces, and make label into a pointer to that string. In C language terms, "Single" is of type const char * and thus cannot be changed in any way. However, you cannot assign a const char * to a char *, since a char * can be modified.
In other words, you cannot write
char label[] = "Single";
label[0] = "T";
because the compiler won't allow the second line. However, you can change info[i].name by writing something like
info[i].name[0] = '[';
because info[i].name if of type char *. To solve this problem, you should use strncpy (I referenced a manual page above) to copy the string "{Kernel}" into info[i].name as
strncpy(info[i].name, "{Kernel}", 256);
info[i].name[255] = '\0';
which will ensure that you don't overflow the buffer.

I think you may be mistaken. The way you would assign this would be one char at a time like so...
name[] = {'a','b','c','d'};

Related

Is there a way to safely collect the data from a returned char*?

I am working on a project for fun to learn C programming, and in Java, I know that I can just obtain a String from a method through a simple return statement. However, in C, I believe it is returning the address of the pointer or garbage data. Here is some basic code:
// In Main Method
char *words = getWords();
// ...
// In getWords
char *getWords() {
char *input; //Well-formatted input.
// Filler code that collects data through file or text entry with 256 max char.
char str[256];
scan("%s", str);
input = str;
return input;
}
You need to pass the pointer as an argument and store the data there itself. Declaring local pointer and returning it is not a good way of doing it. It may lead to dangling pointer.
https://www.geeksforgeeks.org/dangling-void-null-wild-pointers/
After further review, I have discovered that this is the problem:
char str[256];
Should be static:
static char str[256];
Now it returns the correct inputted string.

Adding a null terminator to a string

I have used sscanf to scan in a string and add it to a structure. The only problem is that I cannot print out the string because there is no null terminator added by default. I tried to add a null in there with the strcat() function but came to the realization this cannot work. Thanks for any help.
struct a
{
int *ref;
char string[50];
}rec;
void task()
{
char *p_test;
char test[50] = "9999:STRING OF TEXT";
p_test = test;
sscanf(p_test, "%d:%[^\n]", &rec.ref, rec.string);
printf("String is:%s", &rec.string);
}
There are multiple problems with your code.
test[50] = "9999:STRING OF TEXT";
This is wrong for two reasons.
A) test is an array of char, not an array of char*. So, when you assign a string (a char*) to an element, the address is converted to a char.
B) Element 50 does not exist in your array, and writing to it invokes undefined behavior. You have an array of 50 elements with indices 0...49.
To assign an initial value to your array, all you need do is:
char test[50] = "9999:STRING OF TEXT";
And since test does not need to be modified...
const char *test = "9999:STRING OF TEXT";
If you want to zero an array, the simplest method is:
char test[50] = {0};
Of course, you don't need to if you assign the string properly to begin with, and this is not your problem.
Your string member of the a struct is a char, not a char* (a string), and using the %s format specifier when printing it invokes undefined behavior.
main is defined to return int, not void.
sscanf expects pointers to data to fill in. rec.ref is an int, you need to pass its address, i.e., &rec.ref.
You need to allocate storage for rec.string.
Here is a working example:
#include <stdio.h>
#define STRING_LEN 50
struct a
{
int ref;
char string[STRING_LEN];
} rec;
int main()
{
char test[STRING_LEN] = "9999:STRING OF TEXT";
// note that, in the real world, this may
// be a buffer overflow waiting to happen
sscanf(test, "%d:%[^\n]", &rec.ref, rec.string);
printf("String is:%s, rec is:%d", rec.string, rec.ref);
return 0;
}
You have a number of problems; a lack of null-terminator actually isn't one of them.
One problem is a syntax error; this:
char test[50]
test[50] = "9999:STRING OF TEXT";
is not valid syntax. You need:
char test[50] = "9999:STRING OF TEXT";
Another problem is that rec doesn't have a string (a char * or char[]), it just has a single character (a char). A simple approach, to get you started, is:
struct a
{
int ref;
char string[50];
} rec;
A third problem is that sscanf's arguments all have to be pointers. C is a pass-by-value language; if you just pass in an integer, that doesn't give sscanf any way to modify that integer:
sscanf(test, "%d:%[\n]", &rec.ref, rec.string); // (once rec.string is a pointer)
A fourth problem is that the format-specifier %[\n] does not mean what you seem to want it to mean. (Maybe you actually wanted %[^\n]?)
Other, smaller issues include your return-type for main (it should be int, not void).
The common thread with most of these issues is that your compiler would have eagerly helped you identify them, had you simply turned on compiler warnings!

In c Argument of type char is incompatiple with parameter type const char

I am currently getting the title error within this block of code.
void Option_3(char filename)
{ // profit for a month
FILE *ptr_file;
int num1, num2, num3;
int a[31],b[31],c[31];
int count=0;
int i;
ptr_file = fopen ( filename ,"r"); // error is here at file name
later the main
void main()
{
int select;
char filename;
select = 0 ;
filename = "April.txt"; //here the equals sign is giving me the error.
You need to declare it as char *:
void main()
{
int select;
char *filename; // Note the declaration
select = 0 ;
filename = "April.txt";
Change it on the parameter declaration for Option_3 too:
void Option_3(char *filename)
The reason is that declaring it as char means you have a variable to hold an object of type char. Character sequences in C are arrays of characters terminated by '\0', thus, char * is the correct type.
UPDATE: Even more appropriate is to declare it as const char *, since you can't modify a string literal.
In C the type char is incompatible with the type char *. Simply because they are different types all together. A char is, by definition, guaranteed to be the smallest type (with a size of 1). A char * has the same size as any pointer: it has to be big enough to accomodate a memory address: typically 4 on a 32bit system, 8 on 64bit.
You are assigning a string constant to a variable declared as a char, the assignment expects the right hand argument to be something along the lines of:
char foo = 'a';//single quotes indicate a char
Or, perhaps more what you had in mind:
const char *foo = "April.txt";//double quotes indicative of char *
Note the const storage class: the string constant will not be assigned to the variable, instead the value of filename will be the memory address of the string, which is stored in read only memory. Hence, it's a const: you cannot alter it:
const char *foo = "foobar";
foo[0] = 'F';//<-- ERROR
To be able to modify the value, write:
char foo[] = "foobar";
foo[0] = 'F';//Success!
This will create an array, large enough to accommodate the string, and copy the chars. Of course, if the value of your var is likely to change, it is possible for it to be large enough to accommodate larger strings, too, in which case:
char foo[100] = "up to 100 chars";
strcat(foo, "!!");
Or, using dynamic memory (but avoid, if at all possible, because heap is slower and requires more attention from you):
char *foo = malloc(20);//begin with 20 chars
if (foo == NULL)
exit( EXIT_FAILURE);//no memory could be allocated
strcpy(foo, "foobar");//copy string value into allocated memory
foo = realloc(foo, 50);//increase amount of allocated memory to hold 50
if (foo == NULL)//safety first:
exit(EXIT_FAILURE);
strncat(foo, "some huuuuuuge string", 30);//strncat for safety, again
Ah well, there's a variety of ways to do things, depending on your specific needs

Getting error while initializing structure variable?

I am confused about why I am getting an error while initializing a structure variable. I have found a few related threads on Stack Overflow, but they did not solve my problem. Can anyone explain what is causing the problem?
//I have used Dev-C++ compiler
//Getting an error 'b1' undeclared
struct book
{
char name ;
float price ;
int pages ;
};
struct book b1;
int main()
{
/* First i have tried following way to initialize the structure variable,
but compiler throws the error
b1 = {"John", 12.00, 18};
*/
//I have tried to initialize individually ....but still getting error...?
b1.name = "John";
b1.price = 12.3;
b1.pages = 23;
printf ( "\n%s %f %d", b1.name, b1.price, b1.pages );
system("pause");
return 0;
}
Problems
only one byte memory available for name field. use like char name[100]
use strcpy() instead of b1.name = "John";
You clearly want a string variable in your struct, but you declared it as char name; (a single character).
Instead, use a char pointer (const char *name), or a char array (char name[100]). In the latter case, you will have to use strcpy(b1.name, "John").
The problem is that you have declared name as a char. That means name will hold only a single char, not an entire string.
You can statically allocate name as an array of char:
char name [25] // or whatever length you think is appropriate
// remember to leave room for the NUL character
Then you will need to use strcpy() to copy the actual name into the structure.
Alternatively, you can declare name as a pointer to char:
char* name;
In this case, you can set the pointer to a string literal:
name = "John";
But in most real life situations, this is not an option, as you will be reading the name in from a file or standard input. So you will need to read it into a buffer, set the pointer to dynamically allocated memory on the heap (the string length of the buffer + 1 for the NUL), and then use strcpy().
You have to do some tweaks to your code in order to make it work.
char name; // only one byte is allocated.
Define char array to store strings in C.
char name[20]; //stores 20 characters
char *name; //Pointer variable. string size can vary at runtime.
Once you have created a object for your structure than you can feed data only using that object.
(i.e) object.element=something;
b1 = {"John", 12.00, 18}; // Not possible
The above initialization is possible only while defining objects.
struct book b1={"John", 12.00, 18}; //Possible
If char *name is defined inside struct, you can do the following.
struct book b1;
b1.name="John"; // Possible
b1.price=12.00; // Possible
b1.pages=18; // Possible
If you use char array char name[20] then you can do the following.
struct book b1;
strcpy(b1.name,"John"); // Possible
b1.price=12.00; // Possible
b1.pages=18; // Possible

Doubts in the strcpy function used

I am using two buffers which are of unsigned char and when I used the function strcpy, there is a compilation error which says "invalid conversion of unsigned char * to char *". Can anyone please tell me what difference does an unsigned buffer vs. signed buffer makes to the output? This is the program which I had tried.
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy(buff,dst);
printf("The string is %s\n",buff);
}
Now when i typecast the parametrs passed in strcpy to (char *),This programe works fine as shown below
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy((char *)buff,(char *)dst);
printf("The string is %s\n",buff);
}
2nd Question: Does typecasting to char* in the string function create any issues?
Please do let me know if you need any more inputs.
You can just change:
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
to
char buff[20] = "Michael";
char dst[20] = "Jackson";
To think of it logically, A string cannot be signed or unsigned, it is not a numeric value to be treated that way, it is just an char array and you should declare and use it so.
Why do you get the error?
strcpy has the prototype:
char *strcpy(char *restrict s1, const char *restrict s2);
And what you are passing to it is, unsigned char*, when a function is called parameter type checking takes place and the compiler finds that you are not calling the function with proper type parameters and hence it complains about it, When you apply a cast the function arguments match and hence compilation passes.
Does typecasting to char in the string function create any issues?*
No, in this case it doesn't.
Though it makes more sense to change your usage of unsigned char for the reasons mentioned above in the answer.
Suggestion:
Strcpy is not safe, so you are much better off using strncpy, it allows you to explicitly specify how many characters to copy, rather than rely on null terminator of the source string, Also this helps avoiding buffer overflow since you explicitly specify a length.
The way you are using it should be fine.
But you shouldn't use unsigned char arrays with string handling functions. In C strings are char arrays, not unsigned char arrays. Since passing to strcpy discards the unsigned qualifier, the compiler warns.
As a general rule, don't make things unsigned when you don't have to.
strcpy wants char *'s, plain and simple. Cast your buffers to char *'s and you'll be fine. Then there's the whole safety problem with using strcpy in the first place...

Resources