Access char sequence in arrays of char pointers - c

I have a problem with assigning specific pointer to another char sequence(string);
#include<stdio.h>
void setInformations(char *informations[], char *contests_name[]);
int main(void) {
char *informations[]={"","","",""};
char *contests_name[]={"cycle_race","swim","running race"};
int totalTime=0;
setInformations(informations,contests_name);
getch();
return 0;
}
void setInformations(char *informations[], char *contests_name[]) {
printf("Competitor's name: ");
scanf("%s",*informations[0]);
printf("%s",informations[0]);
}
I know that the problem is assigning string to pointer of type char. How can I replace this (strcpy?)

Take the * out of the scanf:
scanf ("%s", informations[0]);
...and allocate space for the informations array
char* informations[NUMBER_OF_INFORMATIONS][MAX_NAME_LENGTH] = {{'\0'}};
so scanf will have room to put in the info.

here : scanf("%s",*informations[0]);, you are trying to write in a read-only memory.
So you have to allocate the memory in the main :
int stringSize = 30; // example of length
char* informations[3];
informations[0] = malloc(stringSize);
informations[1] = malloc(stringSize);
informations[2] = malloc(stringSize);
//initialyse the strings to "" :
informations[0][0] = '\0';
informations[1][0] ='\0';
informations[2][0] ='\0';
in setInformations(, you have to delete the * to give scanf the adress of the memory where to write). correct syntax : scanf("%s",informations[0]);

Related

How to assign a string to struct variable in C?

I am unable to figure out how to assign a string to a struct variable using only <stdio.h> header file.
The following code gives me an error and I am unable to fix it.
#include <stdio.h>
struct Student
{
char name[50];
};
int main()
{
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
printf("Name : \n",s1.name);
s1.name={"Hussain"};
printf("Name : \n",s1.name);
}
It gives the following error while compilation:
test.c: In function 'main':
test.c:12:12: error: expected expression before '{' token
s1.name={"Hussain"};
^
I have tried initializing it in the following way:
s1.name="Hussain";
But this doesn't work too.
I could avoid this by the use of pointers as follows:
#include <stdio.h>
struct Student
{
char *name;
};
int main()
{
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
printf("Name : %s\n",s1.name);
s1.name="Hussain";
printf("Name : %s\n",s1.name);
}
This code works perfectly fine with no errors.
But I want to know where exactly I am doing wrong with the array, which is making my code not work.
A char array (and arrays in general) can't be assigned a value directly, only initialized. To write a string into a char array, use strcpy.
strcpy(s1.name, "Hussain");
The latter code where the name member is a pointer works for the assignment because the pointer is assigned the start address of the start of the string constant. Also note that you can't (at least not yet) use strcpy in that case because s1.name doesn't point anywhere. You would first need to allocate memory using malloc, or perform both steps at once using strdup. Also for this reason, you can't yet use scanf until you allocate memory.
If you're not allowed to use functions from string.h, then you would need to write the characters into the array one at a time, and then write a terminating null byte at the end.
Arrays do not have the assignment operator. So these assignment statements
s1.name = { "Hussain" };
s1.name = "Hussain";
are invalid.
You could use the standard C string function strcpy to copy elements of the string literal to the array s1.name like
#include <string.h>
//...
strcpy( s1.name, "Hussain" );
If you may not use standard string functions then you need to write a loop as for example
const char *p = "Hussain";
for ( char *t = s1.name; ( *t++ = *p++ ) != '\0'; );
Or
for ( char *t = s1.name, *p = "Hussain"; ( *t++ = *p++ ) != '\0'; );
Pay attention to that the second your program has undefined behavior. The pointer s1.name is not initialized and does not point to a valid object of an array type. So the call of scanf in this code snippet invokes undefined behavior.
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
If you can't use <string.h>, then you have to implement your own version of strcpy():
void copystring(char *dest, const char *src)
{
const char *p = src;
while (*p) {
*dest = *p;
p++;
dest++;
}
*dest = '\0'; // Null-terminate string (as pointed by #Ted)
}
Make sure that dest has enough space to hold src.
Also, avoid using scanf() in your code. Use fgets() as an alternative.
EDIT: As pointed by Jabberwocky, fgets() leaves \n read in the string. But since using <string.h> is not allowed, you have to implement your own function to replace it with a null-terminator:
int findchar(const char *str, char c)
{
int pos;
for (pos = 0; str[pos]; ++pos)
if (str[pos] == c)
return pos;
return -1;
}
You can use it like:
char str[100];
if (!fgets(str, sizeof str, stdin)) {
// fgets() failed. Do something.
} else {
int nwln = findchar(str, '\n');
if (nwln == -1) {
// You probably entered more than 100 characters
// because \n couldn't be found.
} else {
str[nwln] = '\0';
}
}

Double Pointer and Char

I have a problem with the set_ccs function. I cannot take elements from user. How can i fix that?
int main(){
char *ccs;
*ccs =(char*)malloc(sizeof(char) * 80);//i have to use dynamic memory allocation
printf("Enter CCS: ");
set_ccs(&ccs);
free(ccs);
return 0;
}
int set_ccs(char **ccs){
int i = 0;
scanf("%s",*ccs);//Is it better to use fgets? Because scanf seems to count 'enter'
while(*ccs!='\0'){
ccs++;
i++;
}
printf("Length of sequence : %d\n",i);//It always return 3
printf("%s",ccs); //with weird elements
return i;
}
Thanks already.
In addition to unwinds answer that you should just use
char *ccs;
ccs = malloc(80);
You should make the function set_ccs() accept a pointer:
int set_ccs(char *ccs)
And call it like this from your main:
set_ccs(css);
Then in your function you can use scanf() like so:
scanf("%s", css);
Now you if you want to check for '\0', it is good practice to initialize your "string" to 0 before you use it. You can do that with calloc(80) instead of malloc(80).
If you need to have the pointer to pointer (char **ccs), you have to make a double pointer in your main, check this code:
int main(){
char *ccs;
char **ccs2; //a pointer to a pointer
ccs = calloc(80); //i have to use dynamic memory allocation
ccs2 = &ccs; //pass the address of the pointer to the double pointer
printf("Enter CCS: ");
set_ccs(ccs2); //pass the double pointer
free(ccs);
return 0;
}
int set_ccs(char **ccs){
int i = 0;
scanf("%s", *ccs);
char *c = *ccs; //copy to make increments
while(*c != '\0'){
c++;
i++;
}
printf("Length of sequence : %d\n", i);
printf("%s", *ccs);
return i;
}
This:
char *ccs;
*ccs =(char*)malloc(sizeof(char) * 80);
Is wrong, and there is no sane compiler that will accept it. You're shoving a pointer into a char, and it certainly won't fit.
It should just be:
ccs = malloc(80);
There's no need to scale by sizeof (char), that is always 1.
Also, please don't cast the return value of malloc() in C.

Segmentation Fault - String Concatenation in C Error

I am fairly new to C programming and still trying to understand all the nooks and crannies of C. I am writing a program to concatenate two strings. But I am getting an error which I don't understand. Here is the output.
Asfakul
The Length of the String name is 7
The Length of the String fullname is 7
L
Segmentation fault (core dumped)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char const *argv[])
{
char *name="Asfakul";
char *surname="Laskar";
char *fullname;
int i=0;
//Allocate Memory of 100 char
fullname=(char*)malloc(100*sizeof(char));
fullname=name;
while(*name !='\0')
{
i++;
name++;
}
// Allocate Memory for FullName
//fullname=(char*)malloc(100*sizeof(char));
//Coppied the spurce String
// fullname=name; // Here this assignement will not work as Pointer name now point to NULL character of String Name.
puts(fullname);
printf("The Length of the String name is %d\n",i );
printf("The Length of the String fullname is %d\n",strlen(fullname) );
while(*surname !='\0')
{
printf("%c\n",*(fullname+i+1));
*(fullname+i+2)=*(surname);
printf("%c\n",*(surname));
i++;
surname++;
}
puts(fullname);
return 0;
}
Please help me understand what I am doing wrong.
fullname = name; assigns the pointer name to fullname. You subsequently modify the data at name. That's not allowed since name points to a read-only string literal.
You're also discarding the malloc pointer, leaving you no way to free the allocated memory! This will not end well.
You should take a deep copy of name instead: consider using a strncpy.
If you were to use const char* for the string literals then compilation should fail, so protecting yourself from these kind of things.
*(fullname+i+2)=*(surname);
Here you are trying to cat the surname at the end of the name:
char *name="Asfakul";
This is read-only space.
You should alloc enough space for both strings and copy them inside the allocated space.
You can past char by char
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char const *argv[])
{
char *name="Asfakul";
char *surname="Laskar";
char *fullname;
int i=0;
//Allocate Memory of 100 char
fullname=malloc(100*sizeof(char));
while(*name !='\0')
{
fullname[i++] = *name++;
}
fullname[i] = '\0';
puts(fullname);
printf("The Length of the String name is %d\n",i );
printf("The Length of the String fullname is %zd\n",strlen(fullname) );
fullname[i++] = ' ';
while(*surname !='\0')
{
fullname[i++]= *surname++;
}
fullname[i] = '\0';
puts(fullname);
free(fullname);
return 0;
}

How to dynamically allocate a two dimensional array of pointers ? (C)

I have an assignment to make a dictionary.
It will contain an x amount of words and their definitions (input by user).
Instructions say that the dictionary should be of type char*** (2D array of pointers=arrays=strings), but I've got absolutely no idea of how to dynamically allocate the size of the array. it should have 2 lines, 1 for words and another 1 for their definitions, and the number of columns is decided by how many words are in the dictionary. While looking for help online i came up with this:
char** AllocateArray(int line, int column)
{
char** pArray=(char**)malloc(line*sizeof(char*));
int i;
for(i=0;i<2;i++)
pArray[i]=(char*)malloc(column*sizeof(char));
return pArray;
}
What changes should i make in the code for it to work with my char*** ?
Using Visual studio 2012
Edit:
I have a problem with this right now:
void inputString(char* p1)
{
char buffer[80];
printf("\nEnter a word:");
scanf("%s",buffer);
p1=(char*)malloc(strlen(buffer)+1);
if(p1!=NULL)
{
strcpy(p1,buffer);
free(buffer);
}
}
it crashes right after i input a word. the char* that the function receives is dictionary[i][j]. –
Don't free() anything allocated on the stack (i.e. buffer).
Also, your function inputString() will not tell its client what memory it had allocated, since p1 is local to it.
Here is an example.
char*** dictionary;
int i = 0;
int j = 0;
int lines = 10;
dictionary = (char***)malloc(sizeof(char**)*lines);
for(i=0;i<lines;i++)
{
dictionary[i] = (char**)malloc(sizeof(char*)*4);
for(j=0;j<4;j++)
dictionary[i][j] = (char*)malloc(sizeof(char)*25);
}
You have to modify the malloc's parameters in order to adapt to your problem/ or modify them when you need more memory for your strings.
Also it might be a good idea to try and free memory when you do not need it
Don't forget to malloc like this...
dictionary[i][j] = (char*)malloc(sizeof(char)*strlen(word_to_insert)+1);
...because each word end with a supplementary byte filled with 0 "null terminate string".
a sample
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char ***dictionary;
const char *words[] = { "ASEAN", "United Nations", "OPEC" };
size_t howManyWords = sizeof(words)/sizeof(*words);
int i;
dictionary = malloc(howManyWords*sizeof(char**));
printf("Please enter the definition of this word\n");
for(i = 0; i < howManyWords; ++i){
char buff[80];
char **keyValue;
printf("%s : ", words[i]);
fgets(buff, sizeof(buff), stdin);
keyValue = malloc(2*sizeof(char*));
keyValue[0] = (char*)words[i];
keyValue[1] = malloc(strlen(buff)+1);
strcpy(keyValue[1], buff);
dictionary[i] = keyValue;
}
//print
for(i=0;i<howManyWords;++i){
printf("%s : %s", dictionary[i][0], dictionary[i][1]);
}
//release
for(i=0;i<howManyWords;++i){
free(dictionary[i][1]);
free(dictionary[i]);
}
free(dictionary);
return 0;
}

C simple string program does not compile

#include <stdio.h>
#include <string.h>
char Jones(char, char);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
result=Jones(name, surname);
puts(result);
return 0;
}
char Jones(char name, char surname)
{
char result[80];
int length;
length = strlen(surname);
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
return result;
}
The program does not compile and i dont know why. It is supposed to read two strings and swap their places. It should display eg. "Jones Andrew".
Here's one problem:
char name[]="Andrew";
char surname[]="Jones";
char result[80];
wynik=Jones(name, surname);
This calls Jones() with character arrays (which will decay to character pointers), but the function is declared to accept single characters only.
You should change the function to take char *name, char *surname, since it really does seem to expect strings.
Further, you can't return a character array like you're doing in Jones(), you need to read up quite a bit on how to work with strings in C.
Also, wynik looks undeclared, that'll also make it fail to build.
There's a few errors:
char Jones(char, char);
This takes just a single char, not a char * which you need for a string.
result=Jones(name, surname);
Here result is an array. In C, you cannot assign to an array.
char Jones(char name, char surname)
{ char result[80];
...
return result;
}
Here you return result which is a local variable. But to return a string, you'd need to return a char*. But that char* would point to a local variable within the Jones function, which is no longer valid when the function ends. One solution is to pass in a buffer where you write the result that the caller owns.
Your algorithm for combining the surename and name is also wrong, you never do anything with the surename.
You'll need to do this:
char *Jones(char*, char* , char *);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
char *p;
p = Jones(name, surname, result);
puts(p);
return 0;
}
char *Jones(char *name, char *surname, char *result)
{
int length;
int i,k;
length = strlen(surname);
for (i=0; i<length ; i++)
{
result[i] = surname[i];
}
result[i++] = ' '; //add a space
length = strlen(name);
for (k=0; k<length ; k++, i++)
{
result[i] = name[k];
}
result[i] = 0; //add nul terminator to end the string
return result;
}
The conatenation could be simplified in many ways, e.g. to
strcpy(result, surename);
strcat(result, " ");
strcat(result, name);
or the Jones function could just do:
sprintf(result, "%s %s", surename, name);
In all cases, the function is rather fragile, as it's easy to overflow the result buffer if you pass in something else that does not fit within the result buffer.
1) The name and surname are char array and not single char so you have to change the input parameters types of your function Jones() the input parameters types should be char name[] (char array) or char *name (pointer to array of char)
2) You can not return an array defined locally and statically in the function. and if you want to return a string from the function, the string should be constant or it should be a buffer allocated dynamically (with malloc, calloc, realloc) into the function And for both cases the function type should be char *Jonas() and not char Jonas()
Or you can pass the result array via input parametr. and in this case you can fill it into the function.
void Jones(char *name, char *surname, char *result)
and in the main:
char result[80];
Jones(names, surname, result);
3) The following for loop is missing some thing
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
The result elements from element 0 to element length are containing garbage because the result array is not initiated. so when you printf the result array you will get garbages printed. You have to initiate elements between 0 to length in the result array
#include <stdio.h>
#include <string.h>
char* Jones(char*, char*);
int main() {
char name[]="Andrew";
char surname[]="Jones";
puts(Jones(name,surname));
return 0;
}
char* Jones(char *name, char *surname)
{
strcat(surname," ");
strcat(surname,name);
return surname;
}

Resources