Uninitialized Structures c - c

i'm having trouble whit this code. I get the error " uninitialized local variable "question1" used", I'm new to c and I'm really trying to learn. I'm trying to build a quiz program where i can use both Structures and textfile. i'm just staring but the error gets in the way !!
the code is !
#pragma warning(disable:4996)
#include<stdio.h>
#include<stdlib.h>
#define max 70
struct question{
char *questions;
char *alter1;
char *alter2;
char *alter3;
char *alter4;
char correct;
};
int main(){
char *m;
struct question question1;
struct question Alt1;
question1.questions[max] = "what is my name?A:Haidar?B:Ali?C:Hagob?D:Aws?";
Alt1.alter1 = 'A';
Alt1.alter2 = 'B';
Alt1.alter3 = 'C';
Alt1.alter4 = 'D';
Alt1.correct;
m = question1.questions[max];
printf("%s\n", *m);
scanf("%c", &Alt1.correct);
if (Alt1.correct == Alt1.alter1);
{
print("right you have won\n");
}
if ((Alt1.correct) != Alt1.alter1); {
printf("sorry\n");
}
system("pause");
}

question1.questions is a char pointer. When you write question1.questions[max] you are saying "take the current value of the pointer, add (50 times the length of one char) to it, and dereference the result.
But question1.questions was never given an initial value. It is an uninitialized pointer, hence it doesn't point anywhere. You can't, therefore, dereference it.
Since you say it is supposed to be an array of strings, not a single string, your structure definition should look like:
#define max 70
struct question{
char *questions[max];
char *alter1;
char *alter2;
char *alter3;
char *alter4;
char correct;
};
Then questions[0] would refer to the FIRST string. questions[max-1] would be the LAST string. questions[max] would be an error, past the end of the array.

Related

Problem entering values to typedef char array in C

in my code I have this typedef char:
typedef char chessPos[2];
and when I try to debug and see the the values I try to enter
chessPos* pos;
*pos[0] = 'C';
*pos[1] = '3’;
after debugging I get that the values in the array are as such (not a string so I don’t need \0) for some reason the char ‘3’ isn’t in the array and I get \0 instead.
debugging
what can I do ? thanks
You should avoid hiding arrays and pointers behind typedefs. It makes the code impossible to read and leads to curious, unintended side-effects.
In your case chessPos* is actually a char(*)[2] type and *pos[0] gives you pointer arithmetic on such an array pointer type, before de-reference.
Also you can't "store values inside a pointer", that doesn't make any sense. Pointers need to point at valid memory and the values stored in that pointed-at memory, see Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
Drop the array type in the typedef. If you need a custom type, use a struct instead:
typedef struct
{
char coord[2];
} chessPos;
chessPos pos = { 'C', '3' };
Please note that this is not a null terminated string either, so if you intend to use it as such, increase the size to 3 and do "C3" instead.
In your code you define pointer to the two element char array. It does not allocate the memory for that array. If you dereference this pointer it leads to the Undefined Behaviour.
In your code ptr references the char array. When you *pos[1] you dereference the first element of the second char array not the second character in the array. To access second elements of the array you need to dereference pointer first and then use the index (*pos)[1]
You need to allocate the memory for the characters:
#include <stdio.h>
#include <stdlib.h>
typedef char chessPos[2];
int main(void)
{
chessPos* pos;
pos = malloc(sizeof(*pos));
(*pos)[0] = 'C';
(*pos)[1] = '3';
printf("(*pos)[0] = '%c', (*pos)[1] = '%c'\r\n", (*pos)[0], (*pos)[1]);
}
https://godbolt.org/z/8nPxn3TxE
or simple (without the pointer)
#include <stdio.h>
typedef char chessPos[2];
int main(void)
{
chessPos pos;
pos[0] = 'C';
pos[1] = '3';
printf("pos[0] = '%c', pos[1] = '%c'\r\n", pos[0], pos[1]);
}
https://godbolt.org/z/h6fj7c1Ea

Store char variables in other char variables in C

I am trying to do the following, create a multy-charr array with other char variables.
char data_info_1[] = "Wellcome.";
char data_info_2[] = "Please";
char data_info_3[] = "If";
int size_line= sizeof(data_info_1)/sizeof(data_info_1[0]);
char data_info[3][size_line]={{data_info_1},{data_info_2},{data_info_3}};
One solution would be the following one, but I am not interested in just putting the string right in the data_info variable
char data_info[3][size_line]={{"Wellcome"},{"Please"},{"If"}};
Could you please explain me why the first thing that I have writen is not valid. And if there is a solution to my problem.
Thanks.
To answer your question, neither of your solutions is correct, you can't initialize a 2D array of chars like that.
The second option would be valid if it wasn't a variable sized array, i.e.
char data_info[3][10]={"Wellcome", "Please" ,"If"};
^
Valid -> fixed size
Assignments like those would be possibe if you had an array of pointers:
char *data_info[] = {data_info_1, data_info_2, data_info_3}; //1
Or
const char *data_info[] = {"Wellcome", "Please", "If"}; //2
But these may not be what you need.
Option 1 will contain pointers to the original strings, any changes made to them through those pointers will be reflected in the original strings.
Option 2, the pointers are being initialized with string literals and those can't be changed, that's why I added the const qualifier as a metter of safety.
If neither of these constrains work for you, you'll need to copy the strings with something like strcpy, strncpy or better yet memcpy:
#include <string.h>
//...
memcpy(data_info[0], data_info_1, sizeof data_info_1);
memcpy(data_info[1], data_info_2, sizeof data_info_2);
memcpy(data_info[2], data_info_3, sizeof data_info_3);
Arrays may not be initialized by arrays. You may initialize a character array with string literals as you did in this declaration
char data_info[3][size_line]={{"Wellcome"},{"Please"},{"If"}};
Relative to your case you could declare an array of pointers to char like for example
char * data_info[] = { data_info_1, data_info2, data_info3 };
Some remarks:
you do not need to divide by sizeof char becuse it is by definition 1
You can only use constant expressions when defining or initializing global variables char data_info[3][sizeof(data_info_1)];
To "store" one char array in other you need to copy it. Initialization will not work as you cannot assign the arrays.
#include <string.h>
char data_info_1[] = "Wellcome.";
char data_info_2[] = "Please";
char data_info_3[] = "If";
char data_info[3][sizeof(data_info_1)];
void foo(void)
{
strcpy(data_info[0], data_info_1);
strcpy(data_info[1], data_info_2);
strcpy(data_info[2], data_info_3);
}
only structs or unions can be assigned. So you can wrap array into the struct and the assignment or initializations will copy the whole array.
struct stringWR
{
char str[50];
};
struct stringWR data_info_1 = {"Wellcome."};
struct stringWR data_info_2 = {"Please"};
struct stringWR data_info_3 = {"If"};
struct stringWR data_info[3];
void foo(void)
{
data_info[0] = data_info_1;
data_info[1] = data_info_1;
data_info[2] = data_info_1;
}
void bar(void)
{
struct stringWR data_info[3] = {data_info_1, data_info_2, data_info_2};
}

C programming strcat using pointer

I am a beginner in C. I wanted to make strcat function using pointers. I made it but don't know what is wrong with it. I used gcc compiler and it gave segmentation fault output.
#include<stdio.h>
#include<string.h>
char scat(char *,char *);
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
while(*q!='\0') printf("the concatenated string is %c",*q);
}
char *scat(char *s,char *t)
{
char *p=s;
while(*p!='\0'){
p++;
}
while(*t!='\0'){
*p=*t;
p++;
t++;
}
return p-s-t;
}
This one works:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *scat(char *,char *); /* 1: your prototype was wrong */
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
printf("cat: %s\n", q); /* 2: you can use %s to print a string */
free(q);
}
char *scat(char *s,char *t)
{
char *p=malloc(strlen(s)+strlen(t)+1); /* 3: you will have to reserve memory to hold the copy. */
int ptr =0, temp = 0; /* 4 initialise some helpers */
while(s[temp]!='\0'){ /* 5. use the temp to "walk" over string 1 */
p[ptr++] = s[temp++];
}
temp=0;
while(t[temp]!='\0'){ /* and string two */
p[ptr++]=t[temp++];
}
return p;
}
You have to allocate new space to copy at the end of s. Otherwise, your while loo[ will go in memory you don't have access to.
You shoul learn about malloc() here.
It is undefined behaviour to modify a string literal and s, and eventually p, is pointing to a string literal:
char* s = "james";
s is passed as first argument to scat() to which the local char* p is assigned and then:
*p=*t;
which on first invocation is attempting to overwite the null character an the end of the string literal "james".
A possible solution would be to use malloc() to allocate a buffer large enough to contain the concatentation of the two input strings:
char* result = malloc(strlen(s) + strlen(p) + 1); /* + 1 for null terminator. */
and copy them into it. The caller must remember to free() the returned char*.
You may find the list of frequently asked pointer questions useful.
Because p goes till the end of the string and then it starts advancing to illegal memory.
That is why you get segmentation fault.
It's because s points to "james\0", string literal & you cannot modify constant.
Change char *s="james"; to char s[50]="james";.
You need to understand the basics of pointers.
a char * is not a string or array of characters, it's the address of the beginning of the data.
you can't do a char * - char* !!
This is a good tutorial to start with
you will have to use malloc
You get a segmentation fault because you move the pointer to the end of s and then just start writing the data of p to the memory directly following s. What makes you believe there is writable memory available after s? Any attempt to write data to non-writable memory results in a segmentation fault and it looks like the memory following s is not writable (which is to expect, since "string constants" are usually stored in read-only memory).
Several things look out of order.
First keep in mind that when you want to return a pointer to something created within a function it needs to have been malloc'ed somewhere. Much easier if you pass the destination as an argument to the function. If you follow the former approach, don't forget to free() it when you're done with it.
Also, the function scat has to return a pointer in the declaration i.e. char *scat, not char scat.
Finally you don't need that loop to print the string, printf("%s", string); will take care of printing the string for you (provided it's terminated).
At first, your code will be in infinte loop because of the below line. you were supposed to use curely braces by including "p++; t++ " statements.
while(*t!='\0')
*p=*t;
though you do like this, you are trying to alter the content of the string literal. which will result in undefined behavior like segmentation fault.
A sequence of characters enclosed with in double quotes are called as string literal. it is also called as "string". String is fixed in size. once you created, you can't extend its size and alter the contents. Doing so will lead to undefined behavior.
To solve this problem , you need to allocate a new character array whose size is sum of the length of two strings passed. then append the two strings into the new array. finally return the address of the new array.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* scat(char *,char *);
void append(char *t , char *s);
int main(void)
{
char *s="james";
char *t="bond";
char *n = scat(s,t);
printf("the concatenated string is %s",n);
return 0;
}
char* scat(char *s,char *t)
{
int len = strlen(s) + strlen(t);
char *tmp = (char *)malloc(sizeof(char)* len);
append(tmp,s);
append(tmp,t);
return tmp;
}
void append(char *t , char *s)
{
//move pointer t to end of the string it points.
while(*t != '\0'){
t++;
}
while( *s != '\0' ){
*t = *s;
t++;
s++;
}
}

Whats wrong with the given code

I am just learning some pointers stuff in C and I happened to learn that using the * one can dereference the pointer. So I wrote the following code to check for that.
#include<stdio.h>
#include<string.h>
char *findChar(char *s, char c){
while(*s!=c){
s++;
}
return s;
}
int main(){
char myChar='a';
const char myString[]="Hello abhishek";
char *location;
location = findChar(myString,myChar);
puts(location);
char temp = *location;
printf(temp);
}
I assume that temp should get the value pointed by the character pointer location, But this program is giving me a segmentation fault. Please clearify what I am doing wrong?
The following is incorrect:
char temp = *location;
printf(temp);
If you want to print out the char, use the following:
char temp = *location;
printf("%c\n", temp);
The first argument to printf() should be the format string.
The first argument of printf should be char* (for the format), not char.
Try printf("%c\n",temp);
By the way, to see the index of myChar in the array, you may want to print location-myString
The printf causes the segmentation fault, as printf expects a char pointer for temp and you pass a single char to it.

Reversing a string in C

I know this has been asked thousands of times but I just can't find the error in my code. Could someone kindly point out what I'm doing wrong?
#include <stdlib.h>
#include <string.h>
void reverseString(char *myString){
char temp;
int len = strlen(myString);
char *left = myString;
// char *right = &myString[len-1];
char *right = myString + strlen(myString) - 1;
while(left < right){
temp = *left;
*left = *right; // this line seems to be causing a segfault
*right = temp;
left++;
right--;
}
}
int main(void){
char *somestring = "hello";
printf("%s\n", somestring);
reverseString(somestring);
printf("%s", somestring);
}
Ultimately, it would be cleaner to reverse it in place, like so:
#include <stdio.h>
#include <string.h>
void
reverse(char *s)
{
int a, b, c;
for (b = 0, c = strlen(s) - 1; b < c; b++, c--) {
a = s[b];
s[b] = s[c];
s[c] = a;
}
return;
}
int main(void)
{
char string[] = "hello";
printf("%s\n", string);
reverse(string);
printf("%s\n", string);
return 0;
}
Your solution is essentially a semantically larger version of this one. Understand the difference between a pointer and an array. The standard explicitly states that the behviour of such an operation (modification of the contents of a string literal) is undefined. You should also see this excerpt from eskimo:
When you initialize a character array with a string constant:
char string[] = "Hello, world!";
you end up with an array containing the string, and you can modify the array's contents to your heart's content:
string[0] = 'J';
However, it's possible to use string constants (the formal term is string literals) at other places in your code. Since they're arrays, the compiler generates pointers to their first elements when they're used in expressions, as usual. That is, if you say
char *p1 = "Hello";
int len = strlen("world");
it's almost as if you'd said
char internal_string_1[] = "Hello";
char internal_string_2[] = "world";
char *p1 = &internal_string_1[0];
int len = strlen(&internal_string_2[0]);
Here, the arrays named internal_string_1 and internal_string_2 are supposed to suggest the fact that the compiler is actually generating little temporary arrays every time you use a string constant in your code. However, the subtle fact is that the arrays which are ``behind'' the string constants are not necessarily modifiable. In particular, the compiler may store them in read-only-memory. Therefore, if you write
char *p3 = "Hello, world!";
p3[0] = 'J';
your program may crash, because it may try to store a value (in this case, the character 'J') into nonwritable memory.
The moral is that whenever you're building or modifying strings, you have to make sure that the memory you're building or modifying them in is writable. That memory should either be an array you've allocated, or some memory which you've dynamically allocated by the techniques which we'll see in the next chapter. Make sure that no part of your program will ever try to modify a string which is actually one of the unnamed, unwritable arrays which the compiler generated for you in response to one of your string constants. (The only exception is array initialization, because if you write to such an array, you're writing to the array, not to the string literal which you used to initialize the array.) "
the problem is here
char *somestring = "hello";
somestring points to the string literal "hello". the C++ standard doesn't gurantee this, but on most machines, this will be read-only data, so you won't be allowed to modify it.
declare it this way instead
char somestring[] = "hello";
You are invoking Undefined Behavior by trying to modify a potentially read-only memory area (string literals are implicitly const -- it's ok to read them but not to write them). Create a new string and return it, or pass a large enough buffer and write the reversed string to it.
You can use the following code
#include<stdio.h>
#include<string.h>
#include<malloc.h>
char * reverse(char*);
int main()
{
char* string = "hello";
printf("The reverse string is : %s", reverse(string));
return 0;
}
char * reverse(char* string)
{
int var=strlen(string)-1;
int i,k;
char *array;
array=malloc(100);
for(i=var,k=0;i>=0;i--)
{
array[k]=string[i];
k++;
}
return array;
}
I take it calling strrev() is out of the question?
Your logic seems correct. Instead of using pointers, it is cleaner to deal with char[].

Resources