How to store string in array of pointers? - c

I have this write function
char *string_undo[100];
void write()
{
char str[100];
int m=0;
char c;
printf("\nEnter the string: ");
while(1)
{
c = getchar();
if(c=='.')
{
break;
}
str[m] = c;
m++;
}
str[m] = NULL;
(stack_undo[i]) = str;
}
I am trying to store input entered in str to string_undo. It's a 'C' language program so i am having problem with this string assignment. I have tried usign string copy function even its not
working.
The string is not getting saved in stack_undo pointer.

I have forgot much of my C skills but I think you have some errors in your code:
1.-
char *string_undo[100];
In this sentence, you made a table... to store a string in a pointer you can write instead:
char *string_undo = "";
for your function write, it's specially important to initialice it to ""
2.-
char str[100];
If you want to use pointers, I think you can do:
char *str = "";
3.-
str[m] = NULL;
I don't know if it's correct, I allways use
str[m]='\0';
4.-
(stack_undo[i]) = str;
what is "i" variable? It not appears in all the code.. and stack_undo I think you want to write string_undo... test one of these:
string_undo = &str;
I don't know if it's this way or
string_undo = str;
Good luck!

Related

Something weird happens when I try to get user input and print out strings

I'm playing around with user input and printing strings.
Whenever I run the code, the last string that I am trying to print is being glitched and doesn't print out correctly.
my code is:
#include <stdio.h>
int main() {
char inputRoses[] = "";
char inputViolets[] = "";
char inputAnd[] = "";
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
char and[] = "and: ";
printf("\n%s", roses);
scanf("%s", inputRoses);
printf("\n%s", violets);
scanf("%s", inputViolets);
printf("\n%s", and);
scanf("%s", inputAnd);
return 0;
}
Got this in the console:
Roses are: red
Violets are: blue
ue
I also tried this:
#include <stdio.h>
int main() {
char inputRoses[] = "";
char inputViolets[] = "";
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
printf("\n%s", roses);
scanf("%s", inputRoses);
printf("\n%s", violets);
scanf("%s", inputViolets);
return 0;
}
But got this in the console:
Roses are: red
ed
You haven't allocated any memory for the scanned input. char inputRoses[] = "" is an array of one char that contains a null-termination character (value is 0)
You need to allocate some memory and then also limit scanf via a formatter to not overflow this memory space when writing the user input into the buffer.
#include <stdio.h>
int main() {
char inputRoses[50] = "";
char inputViolets[50] = "";
char inputAnd[50] = "";
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
char and[] = "and: ";
printf("\n%s", roses);
scanf("%49s", inputRoses);
printf("\n%s", violets);
scanf("%49s", inputViolets);
printf("\n%s", and);
scanf("%49s", inputAnd);
return 0;
}
Scanf will now limit the the size of the user's input to fit in the memory available for the input buffers. We use the size of the buffer minus one in order to allow for a null terminator at the end of the string.
Results are like:
$ ./a.out
Roses are: red
Violets are: blue
and: stackoverflow has a big cazoo!
You are trying to put many characters in one slot. You must create enough slots in memory for the maximum characters entered. It is also enough to use one input array as buffer unless you want to use them again in the code. Even if it is so, you better use a single input buffer and copy the entered characters to their final destination using strncpy library function.
#include <stdio.h>
int main() {
char input[20]; // Must define the size (of character slots in memory) depending on the max possible input
char roses[] = "Roses are: ";
char violets[] = "Violets are: ";
printf("\n%s", roses);
scanf("%s", input);
printf("\n%s", violets);
scanf("%s", input);
return 0;
}
You should initialize your empty arrays like This:
char inputRoses[60] = "";
char inputViolets[50] = "";
char inputAnd[40] = "";
and your problem solved
this happens because you are declaring an empty character array rather you have to specify the size of your character array and if you want to get dynamic size area then use character pointers.

C - split string and enter into array

I am currently trying to handle string in C and I am having trouble placing the split values of a string into an array. Bellow is the code I have created in an attempt to achieve this.
#include <stdio.h>
#include <string.h>
int main(){
char str[]="titanic.txt";
char parts[2][5];
char *name = strtok(str, ".");
for (int i = 0; i < 2; i++){
parts[i][5] = name;
char name = strtok(NULL, ".");
}
printf("%c\n", str[0]);
return 0;
}
The output I would be expecting from this would hopefully look something like this.
char part[2][10]{
{'t', 'i', 't', 'a', 'n', 'i', 'c'},
{'t', 'x', 't'}
};
alternatively, I have tried something like this using string copy as such.
#include <stdio.h>
#include <string.h>
int main(){
char str[]="titanic.txt";
char parts[2][10];
char *name = strtok(str, ".");
for (int i = 0; i < 2; i++){
strcpy(parts[i], name);
name = strtok(NULL, ".");
}
printf("%s\n", parts[1]);
return 0;
}
Which, did what I want it to, but I would like to try and achieve this without string copy because I feel it will help me understand strings, characters, and arrays better. I do not want to reinvent the wheel I just want a deeper understanding.
The parts array should be an array of pointers, not a 2-dimensional array of characters:
char *parts[2];
Then you assign:
parts[i] = name;
If you want to copy from the input string to parts, you need to declare the 2nd dimension large enough for the largest possible string:
char parts[2][10];
and then you should use strcpy() rather than assignment to copy it.
strcpy(parts[i], name);
Notice that you don't give a second index to parts when doing this, that's only used to access specific characters of the string, not the string as a whole.
In case separating a file name from its extension is actually relevant to whatever you're trying to accomplish, I'll assume you're using Windows and point you to the documentation for the recommended Windows API library for this, <pathcch.h>.
With regard to your actual question, your first code doesn't work because:
You're assigning to a single character in the line parts[i][5] = name;. You're also overflowing since parts[i] has the type char [5], which only has positions 0 to 4.
You redeclare name as a single char rather than a char * pointer, which is the correct type, and was declared as such (correctly) outside the loop scope. Your new variable char name overwrites the existing char *name variable.
You cannot get around using strcpy-family functions to assign to a character array for this (and most other) use cases. The only time the syntax char foo[] = "Hello World"; is valid is immediately on declaration. Also, string literals are stored in read-only memory.
Following your coding style, this is the solution:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "titanic.txt";
char delim[] = ".";
char parts[2][10];
char *ptr = strtok(str, delim);
int i = 0;
for (i = 0; i < 2; i++){
if(ptr != NULL)
{
snprintf(parts[i], sizeof(parts[0]) ,"%s", ptr);
ptr = strtok(NULL, delim);
}
}
printf("'%s'\n", parts[0]);
printf("'%s'\n", parts[1]);
return 0;
}

Getting string with C function

I need to get strings dynamically but as I need to get more than one string, I need to use functions. So far I wrote this
(I put //**** at places i think might be wrong)
char* getstring(char *str);
int main() {
char *str;
strcpy(str,getstring(str));//*****
printf("\nString: %s", str);
return 0;
}
char* getstring(char str[]){//*****
//this part is copy paste from my teacher lol
char c;
int i = 0, j = 1;
str = (char*) malloc (sizeof(char));
printf("Input String:\n ");
while (c != '\n') {//as long as c is not "enter" copy to str
c = getc(stdin);
str = (char*)realloc(str, j * sizeof(char));
str[i] = c;
i++;
j++;
}
str[i] = '\0';//null at the end
printf("\nString: %s", str);
return str;//******
}
printf in the function is working but not back in main function.
I tried returning void, getting rid of *s or adding, making another str2 and tring to strcpy there or not using strcpy at all. Nothing seems to working. Am I misssing something? Or maybe this is not possible at all
//Thank you so much for your answers
Getting the string part can be taken from this answer. Only put a \n as input to the getline funtion.
char * p = getline('\n');
Three things :-
don't cast malloc, check if malloc/realloc is successful and sizeof is not a function.
The problem is not with the function that you are using, but with the way you try copying its result into an uninitialized pointer.
Good news is that you don't have to copy - your function already allocates a string in dynamic memory, so you can copy the pointer directly:
char *str = getstring(str);
This should fix the crash. A few points to consider to make your function better:
main needs to free(str) when it is done in order to avoid memory leak
Store realloc result in a temporary pointer, and do a NULL check to handle out-of-memory situations properly
There are two things to take away from the lesson as it stands now:
(1) You should have one way of returning the reference to the new string, either as an argument passed by reference to the function OR as a return value; you should not be implementing both.
(2) Because the subroutine your teacher gave you allocates memory on the heap, it will be available to any part of your program and you do not have to allocate any memory yourself. You should study the difference between heap memory, global memory, and automatic (stack) memory so you understand the differences between them and know how to work with each type.
(3) Because the memory is already allocated on the heap there is no need to copy the string.
Given these facts, your code can be simplified to something like the following:
int main() {
char *str = getstring();
printf( "\nString: %s", str );
return 0;
}
char* getstring(){
.... etc
Going forward, you want to think about how you de-allocate memory in your programs. For example, in this code the string is never de-allocated. It is a good habit to think about your strategy for de-allocating any memory that you allocate.
Let's simplify the code a bit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getstring()
{
char c = 0;
int i = 0, j = 2;
char *str = NULL;
if ((str = (char*) malloc(sizeof(char))) == NULL)
return NULL;
printf("Input String: ");
while (c = getc(stdin)) {
if (c == '\n') break;
str = (char*) realloc(str, j * sizeof(char));
str[i++] = c;
j++;
}
str[i] = '\0';
printf("getstring() String: %s\n", str);
return str;
}
int main()
{
char *str = getstring();
printf("main() String: %s\n", str);
free(str);
return 0;
}
Then execute:
$ make teststring && ./teststring
cc teststring.c -o teststring
Input String: asdfasfasdf
getstring() String: asdfasfasdf
main() String: asdfasfasdf

string input parameter for c program

I wrote a function to replace the blank spaces with tab character. But when I tried to implement it using function. I am quite not understanding how to call this function. I need functions
Which takes string from user as input,
Second function which replaces the blank space with tab character,
Function to print the modified string.
I achieved second one:
void SecondFunction()
{
char string[] = "I am new to c";
char *p = string;
for (; *p; ++p)
{
if (*p == ' ')
*p = '\t';
}
printf(string);
}
And when I tried to call this function like:
int main()
{
SecondFunction("Hi s");
}
By changing my function to:
void SecondFunction(char* str)
{
char string[] = str;
char *p = string;
....
...etc
}
I get the following error:
error: invalid initializer
char string[] = str;
^
Please, can anybody help me to write the 3 functions of my requirement?
Reading user input
To read input from the user you can use scanf. You need to pass it the memory address of the variable where you want to store the input:
char userinput[256]; // make it large enough to hold what the user inputs
scanf("%s", userinput); // array decays to pointer so no '&' here
The %s means were reading string input. We could also read an int using %d, like this:
int i;
scanf("%d", &i); // note the address-of operator '&' to get the address of i
Printing variables
Your SecondFunction is almost correct. To printf a C-string you need to use a syntax similar to when you scanf to a variable:
printf("%s", string);
Similarly, you could print the int i like this:
printf("The number is: %d", i);
Copying C-strings
When you tried doing this: char string[] = str, that's not possible. Arrays cannot be assigned or even copy constructed.
Just in case for the future, when you want to copy a C-string, you need to use strcpy:
char string[256]; // again, must be large enough to hold the new contents
strcpy(string, str); // copies from str to string
So in conclusion, your function could look something like this:
void SecondFunction(char* str)
{
char string[256];
strcpy(string, str);
char *p = string;
for (; *p; ++p)
{
if (*p == ' ')
*p = '\t';
}
printf("%s", string);
}
Bonus: Why you can't write to the str parameter directly
When you write this: SecondFunction("Hi s"), the string "Hi s" gets stored in a read-only memory segment.
If you then go and try to modify the parameter inside SecondFunction, you get undefined behavior, possibly a segmentation fault.

passing tokens from array to strcmp

What I am trying to do is to break the user input in parts with whitespace as a delimiter, copy the parts into the array (tokenAr) and compare the tokenAr[0] (the first part) if it is equal to sHistory. if they are equal, check the value of tokenAr[1] if it is "1", "2" etc, to execute the corresponding command that is entered in the history array. This is what i have tried to far and it crashes. I am using TCC on Windows x64.
EDIT: I forgot to mention that I began learning C, just two days ago.
EDIT2: I run the program in a debugger and it has raised an Acces Violation(Segmentation Fault) in line if(strcmp(tokenArPtr[0],sHistory)==0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i=1; int j=1; int k=0;
char history[100][100] = {0};
char sKey[] = "exit";
char sInput[100];
char sHistory[]="history";
do
{
//gather user input
printf ("hshell> ");
fgets (sInput, 100, stdin);
strcpy(history[i],sInput);
i++;
//END_gather user input
//Tokenizing
char delims[] = " ";
char *tokenArPtr[5];
char *result = NULL;
result = strtok(sInput, delims);
tokenArPtr[0] = result;
while (result!=NULL)
{
puts(result);
result= strtok(NULL, delims);
tokenArPtr[k+1] = result;
puts(tokenArPtr[k]);
puts("=====");
k++;
}
k=0;
/*
//END_Tokenizing
if(strcmp(tokenArPtr[0],sHistory)==0)
{
for(j=1;j<i;j++)
{
printf("%d. %s \n",j,history[j]);
}
}
else if (strcmp (sKey,tokenArPtr[0]) != 0)
{
printf("\nCommand not found \n");
}*/
}while (strcmp (sKey,sInput) != 0);
return 0;
}
EDIT 3: I used the result variable instead of the tokenArPtr directly, but when debugging, I noticed that the values of the array are not being updated.
Which type does strtok return? char *. What is the type of tokenAr[k]? char. What type does strcmp expect as input? char * and char *. What is the type of tokenAr[0]? char.
See a problem? You should. The * is pretty significant.
Assuming tokenAr is declared like char *tokenAr[2];, how many char * values can tokenAr store? What happens when k exceeds 2? You need to ensure you don't overflow your tokenAr array.
history is uninitialised. Using an uninitialised variable is undefined behaviour. I suggest initialising it, like this: char history[100][100] = { 0 };
Which book are you reading?
While tokenizing, the loop will never end because the test is on the variable "result" that will never change... So you're finally going to a buffer overflow with "tokenAr"... Modify your code to test "tokenAr".
Edit: And tokenAR should be an array... (I don't know how it can compile...)
There are many problems... First of all you should include string.h which will show you some errors in compilation.
I believe that the main problem is here:
char tokenAr[2];
result = strtok(sInput, delims);
while (result!=NULL)
{
tokenAr[k] = strtok(NULL, delims);
k++;
}
tokenAr should be an array of pointers, not chars. And are you sure that k will never exceed 2? An assertion would help debugging.

Resources