i tried to take input from user
input type is not determined(can be char or int)
i wanna take input and store in pointer array
while i doing that job forr each pointer i wanna take place from leap area
that is using malloc
but below code doesnot work why???
int main(void)
{
char *tutar[100][20],temp;
int i;
int n;
i=0;
while(temp!='x')
{
scanf("%c",&temp);
tutar[i]=malloc(sizeof(int));
tutar[i]=temp;
++i;
}
n =i;
for(i=0;i<=n;++i)
{
printf(" %c ",*tutar[i]);
}
printf("\n\n");
/*for(i=0;i<=n;++i)
{
printf("%d",atoi(*tutar[i]));
}
*/
}
note that;
this cite has problem when rewrite(edit) the previous mail
it is general problem or not
There are several problems in your code, including:
you declare tutar as a two-dimensional array of pointers to character, then use it as a one-dimensional array
tutar[i]=temp assigns the value of temp (a char) to tutar[i] (a pointer to char), effectively overwriting the pointer to the newly reserved memory block
you don't initialize temp, so it will have garbage value - occasionally it may have the value x, in which your loop will not execute
Here is an improved version (it is not tested, and I don't claim it to be perfect):
int main(void)
{
char *tutar[100], temp = 0;
int i = 0;
int n;
while(temp!='x')
{
scanf("%c",&temp);
tutar[i]=malloc(sizeof(char));
*tutar[i]=temp;
++i;
}
n =i;
for(i=0;i<=n;++i)
{
printf(" %c ",*tutar[i]);
}
printf("\n\n");
}
Note that unless you really need to allocate memory dynamically, you would be better off using a simple array of chars:
char tutar[100], ...
...
while(temp!='x')
{
scanf("%c",&temp);
tutar[i++]=temp;
}
...
For the sake of brevity, I incremented i within the assignment statement.
Related
In what way is the following code faulty or undefined behaviour?
I suggested this as a possibility to create an array of strings, if string number and size are unknown beforehand, and after a short discussion, it was suggested that I open a new question.
The following code produced the expected results when I compiled it with gcc, but that can happen in spite of undefined behaviour (it's undefined after all).
So, what is the mistake?
int n, i;
printf("How many strings? ");
scanf("%d", &n);
char *words[n];
for (i = 0; i < n; ++i) {
printf("Input %d. string: ", i + 1);
scanf("%s", &words[i]);
}
for (i = 0; i < n; ++i) {
printf("%s\n", &words[i]);
}
Edit:
I feel stupid now for missing this, I guess getting the correct answer back just made me miss my error. But that others may learn from my mistake:
I guess I got completely wrong what the & operator does. I thought it would give me where words points to, but of course it does the exact opposite. See the answers.
scanf("%s", &words[i]); and printf("%s\n", &words[i]); invokes *undefined behavior because data having wrong type are passed.
In both of scanf() and printf(), %s requires char* pointing at valid buffer but what is passed are char**.
Also don't forget to allocate buffer to store strings before reading.
Try this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i;
printf("How many strings? ");
scanf("%d", &n);
char *words[n];
for (i = 0; i < n; ++i) {
printf("Input %d. string: ", i + 1);
words[i] = malloc(1024001); /* allocate enough buffer */
if (words[i] == NULL) {
perror("malloc");
return 1;
}
scanf("%1024000s", words[i]); /* limit length to read to avoid buffer overrun */
}
for (i = 0; i < n; ++i) {
printf("%s\n", words[i]);
}
for (i = 0; i < n; ++i) {
free(words[i]); /* clean what is allocated */
}
return 0;
}
char *words[n];
creates an array of uninitialized pointers
scanf("%s", foo);
writes values to the position foo is pointing to
it is not specified where the pointers of words are pointing to so they could point anywhere which could result in a segfault
next words is a char**
words[i] is a char *
&words[i] is a char **
%s expects a char* so it's again undefined behavior what happens
so you first have to initialize your words arrays using for example malloc and then write the values to words[i]
This:
char *word;
is a pointer, Before it is used as a container for say a string, it needs to point to memory sufficient for the string.
for example, this will work
word = malloc(80*sizeof(*word));
if(word)
{//success, continue
Similar to above, this:
char *word[n];
extension is an an array of n pointers. Before any of the pointers can be used as a container for say some strings, each needs to point to its own memory location. Assuming the value n has been scanned in, this will work:
for(int i=0;i<n;i++)
{
word[i] = malloc(80*sizeof(*word[i]));//80 for illustration
if(!word[i])
{//handle error...
Once the memory is allocated, the strings can be populated.
However, to ensure user input does not overflow the buffer defined by each instance of word, use a width specifier in the format string:
Change:
scanf("%s", &words[i]);
To:
scanf("%79s", words[i]);//note & is not needed as the symbol for a char array serves as the address
// ^^ ^
String manipulation in C is the bane of my existence, I have tried to understand how to manipulate char arrays and fall short of grasping it every time. I simply want to do this in C.
Method1 passes ["1298","9"]
Method2 receives and converts them both to ints
int method1(){
char *values[2];
int i = 1298;
int j = 9;
//sprintf(values,"%d" "%d",i,j);
sprintf(&values[0],"%d" ,i);
sprintf(&values[1],"%d" ,j);
method2(values,2);
}
int method2(char *strings, int num_values){
int i, j;
char buffer[256];
sscanf(buffer, "%d" "%d", &i, &j);
printf("i: %d, j: %d\n",i,j);
return 0;
}
The result of this is 1 and 9; but i want 1298 and 9
Please even after providing an answer, can you explain why it is the way it is?
char *values[2];
The above line is parsed as char *(values[2]);, i.e., [] take precedence over *. This means that values is an array with 2 elements. The type of the elements is char *. So, values[0] and values[1] are of type char *. Since you haven't initialized the array elements, the two items in the array have unknown, random values.
//sprintf(values,"%d" "%d",i,j);
Although you have commented this out, it seems like you were trying to store the string representation of i and j into values using one sprintf call. As you probably found out, this is impossible.
sprintf(&values[0],"%d" ,i);
Here, you are calling sprintf to store the string representation of i into the memory location pointed to by values[0]. But as noted above, values[0] is not pointing anywhere useful, since you haven't initialized it. This is bad.
sprintf(&values[1],"%d" ,j);
Same as above.
method2(values, 2);
Here, you are calling method2, but you haven't declared the signature of method2. As it turns out, method2 takes a char * and an int. You are passing values and 2. values is an array of char *, which gets converted to a pointer in this context, so method2 should take a char ** and an int.
int method2(char *strings, int num_values){
This should be: int method2(char **strings, int num_values) {
int i, j;
char buffer[256];
sscanf(buffer, "%d" "%d", &i, &j);
I am not sure what you are trying to do here. You are ignoring strings, but instead using a buffer variable. buffer is uninitialized, so trying to interpret the data in it as two integers is pointless.
I am assuming you are writing this program to understand strings, pointers, and functions. As such, there is no single correct way to do what you are trying to do. But here is one approach:
#include <stdio.h>
/* Define method2 before method1, so that its definition is visible
in method1 */
/* Assume that method2 will be called with one char * containing two integer
values. I also changed the return type to void since you weren't really
using the int return value. Same for method1. */
void method2(const char *strings)
{
int i, j;
sscanf(strings, "%d %d", &i, &j);
printf("i: %d, j: %d\n",i,j);
}
void method1(void)
{
/* Changed values to a char array that has enough space */
char values[256];
int i = 1298;
int j = 9;
sprintf(values, "%d %d", i, j);
method2(values);
}
int main(void)
{
method1();
return 0;
}
The above outputs:
i: 1298, j: 9
There are a lot of moving parts in your program. I recommend that you learn the basics about pointers, arrays etc., in C, before passing them around in functions.
The result of your program is called UNDEFINED BEHAVIOR. You MUST use compiler warnings if you are learning.
Your code has many issues, you should READ about strings in c instead of trying stuff just to see if they work.
You are using sprintf() wrong, you should pass a pointer to char as the first parameter, that points to valid data. You are passing uninitialized pointers instead which leads to undefined behavior.
Function method1() (please note, that methods are for classes or objects, in c there are no methods, just functions) is also not passing anything anywhere. The array of pointer values is local to the function and is not accessible from outside the function. To pass something to a function you should do it through the parameters instead and it would be the other way around since you can't call main() from a c program because it is undefined behavior.
You are using sscanf() where you apparently what fscanf() or just scanf().
If you want to read input from the user use
if (scanf("%d %d", &i, &j) == 2)
printf("i: %d, j: %d\n", i, j);
else
printf("Invalid input\n");
you can substitute scanf() with fscanf(stdin, ... or another FILE * object to read from a file.
In your code, your program is expecting buffer to contain a string (a sequence of bytes terminated with a '\0'). You are passing an uninitialized array instead which invokes undefined behavior.
If you want to test how sscanf() works, do this
char buffer[] = "1 2";
if (sscanf(buffer, "%d %d", &i, &j) ...
the rest is the same.
I would say, that you want this
int
main(void)
{
char buffer[256];
int i;
int j;
sprintf(buffer, "%d %d", 1289, 9); // - This is not necessay, but for illustration
// - This is also, unsafe as it could cause
// a buffer overflow.
if (sscanf(buffer, "%d %d", &i, &j) == 2) // Would be surprised if this is false,
printf("values: %d %d\n", i, j); // but you MUST always check to make
else // sure, because this kind of situation
printf("invalid input?\n"); // is very unusual in real code.
}
I hope you can see, why your code is SO wrong. You can also move the part you want to the function. But it should be the right part.
Here's something I wrote up quickly; you can pass an array of strings to this function along with it's length and it will dynamically allocate an array of integers with their converted values.
The pitfall here is that with strtol: if it fails to convert one of the strings it will default to 0. So if an element in your array of strings happens to contain some non-numeric characters you may not get what you expect; and an error won't be reported as you'd have to also confirm that the string itself wasn't 0.
#include <stdlib.h>
#include <stdio.h>
int *convert_to_int_array(const char **strings, size_t length) {
int *numbers = malloc(length * sizeof(int));
size_t i = 0;
if(numbers == NULL)
return NULL;
for(i = 0; i < length; i++) {
numbers[i] = strtol(strings[i], NULL, 10);
}
return numbers;
}
int main(int argc, char **argv) {
const char *strings[2];
strings[0] = "100";
strings[1] = "50";
int *numbers;
size_t length = 2, i;
numbers = convert_to_int_array(strings, length);
if(numbers == NULL) {
fprintf(stderr, "failed to initialize numbers\n");
}
for(i = 0; i < length; i++) {
printf("%d\n", numbers[i]);
}
return EXIT_SUCCESS;
}
Try this:
char values[10];
int i = 1298;
int j = 9;
sprintf(values,"%d %d",i,j);
I'm making a program where user enters grades (1 to 5) and then the grade gets added to array for later inspection. When user enters letter "s", the program closes. When ran my program crashes, why?
#include <stdio.h>
#include <stdlib.h>
int i;
int grade[50];
char *num[20];
int enter();
int enter()
{
for (i=0; i<10; i++) {
printf("\nEnter grade:\nPress [s] to close program\n");
scanf("%s",&num[i]);
if (strcmp(num[i],"s") == 0) {
break;
} else {
grade[i] = atoi(num[i]);
}
}
}
int main()
{
enter();
for (i=0; i<10; i++) {
printf("\n%d",grade[i]);
}
return 0;
}
remove ' * ' from num[20] declaration, as you are declaring 20 character string pointers, so reading and comparing values with num[i] will cause error.
Besides, you just nead a simple string to get the grade.
The reason why program crashed is that num is a pointer array, the element of num can not pointer to valid memory which used to store the string you inputed.
you can change char *num[10] to char num[10][12] and 'scanf("%s", &num[i])to scanf("%s", num[i]), and that everything will be OK.
Of course, you can use malloc to dynamic alloc memory for each element in num, like:
`for(i = 0; i < 10; i ++){
num[i] = (char*)malloc(sizeof(char) * 12);
}
`
Even thought, you must change scanf("%s", &num[i]) to scanf("%s", num[i]);
Finally, you can not forget to free the memory you just dynamic malloc.
I am trying to solve a C problem where I have to sort n strings of characters using pointers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void sort (char *s, int n)
{
int i,j; char aux[]="";
for (i=1;i<=n-1;i++)
{
for (j=i+1;j<=n;j++) //if s[i]> s[j] switch
{
if (strcmp(*(s+i),*(s+j))==1)
{
strcpy(aux,*(s+i);
strcpy(*(s+i),*(s+j));
strcpy(*(s+j),*(s+i));
}
}
}
}
void show(char *s, int n)
{
int i;
for (i=1;i<=n;i++)
{
printf("%s",*(s+i));
}
}
int main()
{
int i,n; char *s;
printf("give the number of strings:\n");
scanf("%d",&n);
s=(char*)calloc(n,sizeof(char));
for (i=1;i<=n;i++)
{
printf("s[%d]= ",i);
scanf("%s",s+i);
}
sort(s,n);
show(s,n);
return 0;
}
The warnings that I get are when I use strcmp to compare and when I use strcpy to switch *(s+i) and *(s+j) values.
"passing argument 2 of strcmp makes pointer from integer without a cast"
The warnings that I get are when I use strcmp to compare and when I use strcpy to switch *(s+i) and *(s+j) values.
"passing argument 2 of strcmp makes pointer from integer without a cast"
You are wrong argument to strcmp and strcpy. Signature of strcmp and strcpy are
int strcmp(char *string1, char *string2);
char *strcpy(char *dest, const char *src)
But you are passing it the arguments of char type. Removefrom(s+i)and*(s+j)`. It should be
if (strcmp((s+i), (s+j))==1)
{
strcpy(aux, (s+i));
strcpy((s+i), (s+j));
strcpy((s+j), (s+i));
}
Another problem is you have not allocated memory for the pointer s. For characters, you can declare it as
s = malloc ( (n + 1)*sizeof(char) );
or simply
s = malloc ( n + 1 ); // +1 is for string terminator '\0'
You seem to have mis-understood the return value of strcmp(); it's an integer that will be 0 (zero) if and only if the two string arguments are equal. You're testing for 1, which it will only be rarely; it has no specific meaning.
Consider just using qsort().
You're allocating space for n strings of 1 byte each. The easiest approach is to assume each string will be less than some set length, like 40 bytes. Then you would allocate the memory like this:
s=(char*)calloc(n*(40),sizeof(char));
Then your scanf needs to be modified:
scanf("%s",s+(i*40));
Now, string 1 will be at *s, string 2 will be at *(s+40), etc. Keep in mind that a string ends with a null character (0x00), so the string can only contain 39 chars. Any unused data will also be 0x00.
Do the same s+(i*40) for the sorting algorithm, compare to >0, not ==1, and strcmp, strcpy expect pointers. Then you should be good.
In your code there are a lots of mistakes: in variable declarations, memory allocation and pointer usage.
First remember that you should always reserve enough space to store your string values, and be aware to don't try to store a string with a length greater then the reserved space.
Also you should be very careful managing pointers (s+1 doesn't point to the first string but to the second one, s+n points out of the allocated memory)
So, as mentioned in other answers you should decide the maximum size of your strings an then allocate for them the right amount of memory.
Then I suggest you to use a pointer to strings, i.e. a char** to access your strings and manage the sort, in this way the code is more readable and the sort is faster (you don't need to copy strings, but only to switch pointers)
So your main function should be:
int main()
{
int i, n;
// Declare the pointer to the memory where allocate the space for the strings
char* a; // points to a char ( == is a string)
// Declare the pointer to the memory where store the pointer to the strings
char** s; // points to a char* ( == is a pointer to a string)
printf("give the number of strings:\n");
scanf("%d", &n);
// Allocate the memory for n strings of maximum 40 chars + one more for the null terminator
a=(char*)calloc(n*41, sizeof(char));
// Allocate memory for n pointers to a string
s=(char**)calloc(n, sizeof(char*));
// Notice the 0-based loop
for (i=0; i<n; i++)
{
s[i] = a + i*41; // set the i-th element of s to point the i*41-th char in a
printf("s[%d]= ", i);
scanf("%40s", s[i]); // read at least 40 characters in s[i],
// otherwise it will overflow the allocated size
// and could generate errors or dangerous side effects
}
sort(s,n);
show(s,n);
// Remember always to free the allocated memory
free(s);
free(a);
return 0;
}
the sort function sorts an array of pointers, without copying strings:
void sort (char** s, int n)
{
int i, j;
char* aux;
// Notice the 0-based loop
for (i=0; i<n; i++)
{
for (j=i+1; j<n; j++) //if s[i]> s[j] switch
{
if (strcmp(s[i], s[j])>0)
{
// You don't need to copy strings because you simply copy pointers
aux = s[i];
s[i] = s[j];
s[j] = aux;
}
}
}
}
finally the correct show function:
void show(char** s, int n)
{
int i;
// Notice the 0-based loop
for (i=0; i<n; i++)
{
printf("%s", s[i]);
}
}
I can't test the code but it should works
Added other options
1) If you have troubles with dynamic memory allocation you can use instead static allocation, your main function then will be:
int main()
{
int i, n;
// Declare an array of fixed lenght strings
char s[100][41]; // You manage max 100 strings
printf("give the number of strings:\n");
scanf("%d", &n);
// Ensure that n is less or equal maximum
if (n>100)
{
printf("you'll be asked for a maximum of 100 strings\n");
n=100;
}
// Notice the 0-based loop
for (i=0; i<n; i++)
{
printf("s[%d]= ", i);
scanf("%40s", s[i]); // read at least 40 characters in s[i],
// otherwise it will overflow the allocated size
// and could generate errors or dangerous side effects
}
sort(s,n);
show(s,n);
// You don't need to free any memory
return 0;
}
all other functions remain unchanged.
2) Whereas, if you want the maximum freedom in the memory you need you can choose a two allocate memory separately for each string only for the needed size, in this case your main funcion will be:
int main()
{
int i, n;
char buffer[1000]; // You need a buffer to read input, before known its actual size
// Declare the pointer to the memory where store the pointer to the strings
char** s; // points to a char* ( == is a pointer to a string)
printf("give the number of strings:\n");
scanf("%d", &n);
// Allocate memory for n pointers to a string
s=(char**)calloc(n, sizeof(char*));
// Notice the 0-based loop
for (i=0; i<n; i++)
{
printf("s[%d]= ", i);
scanf("%999s", buffer); // read at least 999 characters in buffer,
// otherwise it will overflow the allocated size
// and could generate errors or dangerous side effects
// Allocate only the memory you need to store the actual size of the string
s[i] = (char*)calloc(strlen(buffer)+1, sizeof(char)); // Remember always 1 more char for the null terminator
// Copy the buffer into the newly allocated string
strcpy(s[i], buffer);
}
sort(s,n);
show(s,n);
// Remember always to free the allocated memory
// Now you have first to free the memory allocated for each string
for (i=0; i<n; i++)
{
free(s[i]);
}
// Then you can free the memory allocated for the array of strings
free(s);
return 0;
}
all other functions remains unchanged too.
If i want to take an input in a 2d array with each string in one row, and the next in the other(i.e. change the row on pressing enter). How can i do that in C. C doesnt seem to have convenient "String" Handling. I obviously mean doing so without the use of getchar().
3 ways are there which are mentioned below.
If you know the maximum number of strings and maximum number of chars, then you can use the below way to declare a 2D character array.
char strs[MAX_NO_OF_STRS][MAX_NO_CHARS] = {0};
for (i = 0; i < MAX_NO_OF_STRS; i++)
{
scanf("%s", strs[i]);
}
If you know the maximum number of strings, and you dont want to waste the memory by allocating memory for MAX_NO_CHARS for all strings. then go for array of char pointers.
char temp[MAX_NO_CHARS] = {0};
char *strs[MAX_NO_OF_STRS] = NULL;
for (i = 0; i < MAX_NO_OF_STRS; i++)
{
scanf("%s", temp);
strs[i] = strdup(temp);
}
If you know the maximum number of strings during run time means, you can declare a double pointer of char. Get the number of strings n from user and then allocate memory dynamically.
char temp[MAX_NO_CHARS] = {0};
char **strs = NULL;
int n = 0;
scanf("%d", &n);
strs = malloc(sizeof(char*) * n);
for (i = 0; i < n; i++)
{
scanf("%s", temp);
strs[i] = strdup(temp);
}
#include<stdio.h>
main()
{
char student_name[5][25];
int i;
for(i=0;i<5;i++)
{
printf("\nEnter a string %d: ",i+1);
scanf(" %[^\n]",student_name[i]);
}
}
u can read strings using 2d array without using getchar() by putting space in scanf(" %[^\n]")
; before %[^\n]!
An alternative to using malloc and filling up an array of pointers with buffers of a fixed size, would be to allocate a 2d array (in static storage or on the stack) and fill it up. KingsIndian modifed code example would than look like this:
#include <stdio.h>
int main()
{
char str[2][256] = {{0}};
int i = 0;
for(i=0;i<2;i++)
{
scanf("%255s", &str[i][0]);
}
return 0;
}
If all strings you expect to get are no longer than some size, than this approach will spare you the need to deal with freeing the memory yourself. It is less flexible however, meaning that you can't fit the size of an individual buffer to the string it contains.
EDIT
Adding to the information in the comment, to read a string that is terminated only by a new-line, rather than by any whitespace:
scanf("%255[^\n]", str[i]);