I'm trying to read a string from argv. It should be something like a mathematical function like "-x^2-5" etc.
I've got something like this:
void test(char *function){
int temp = 0;
for (int i = 0; i < strlen(function); i++){
if((function[i] != '+') && (function[i] != ...){
// function[i] is a digit, but still as a char
temp = atoi(function[i]);
}
}
//...
}
int main(int argc, char **argv){
test(argv[1]);
//...
}
This works quite well until the last lap of the loop.
If I use printf("%c", function[i]);, it sais, it's 5.
But atoi(function[i]) gives a segfault. Why?
Right. Let's first take a look at the signature of atoi.
int atoi(const char *str);
Now, what you are passing to it is function[i], and since function is of type char *, function[i] is a char. And your character is most likely not a proper character pointer.
What you'd want to pass to atoi is instead a const char *, which you can get by calling atoi(&function[i]);
As already said by #sham1, atoi expects its parameter to be a C string, this is a null terminated char array, while you have a single char.
But digits are special, because they are required to have consecutive codes. So if you know that a character (say c) is a digit, its value is c - '0'. So you can write:
if((function[i] != '+') && (function[i] != ...){
// function[i] is a digit, but still as a char
temp = function[i] - '0'; // get the int value of a digit character
}
Besides the bug pointed out in other answers, atoi doesn't have any reliable error handling, which is why it is one of the standard library functions that should never be used.
Just forget that you ever heard about atoi and replace it with:
char* endptr;
int result = strtol(str,&endptr,10);
if(endptr == str)
{
// some conversion error
}
strtol is also able to convert an initial part of the string if it contains valid numbers.
Related
I'm passing values beteween childs and need to store some values to later use.
the definitions and use in functions
char fouts[MAX_SIZE][10];
the function where i give the array the values:
void connect(char *nodo, char *out[], int nouts) {
(...)
for(i=0;i<nouts;i++) {
fouts[fnum][i] = out[i];
}
(...)
and the function where i'm trying to use them:
void disconnect(char *nodo, char *remover){
char *outs[10];
nouts = fnouts[getfnum];
int m =0;
for(i=0;i<nouts;i++) {
if(strcmp(fouts[getfnum][i],nodo) != 0) { outs[m] = fouts[getfnum][i]; m++ ; }
}
no matter what i did to try to fixm everytime it tries to execute this last for, it gives a segmentation fault.
have tried somethings (read fouts[getfnum][0] for example directly and gives a segmentaton fault, but fouts[getfnum] gives "trash")
check the value after it been atributed fouts[fnum][i] = out[i]; here and it checks out, so i guess that part is ok).
don't know if its something obvious or not, but any help?
You are mixing char and char*.
fouts[fnum][i] is a char
and
out[i] is a char pointer
So in this line
fouts[fnum][i] = out[i];
you assign a char pointer to a char which is illegal.
And in this line
if(strcmp(fouts[getfnum][i],nodo) != 0)
you pass a char (i.e. fouts[getfnum][i]) to strcmp.
That is not legal as strcmp expects a char*
From the posted code, it is hard to tell how to fix the problems. Maybe you just need:
char* fouts[MAX_SIZE][10];
I'm trying to convert a char * to uppercase in c, but the function toupper() doesn't work here.
I'm trying to get the name of the the value of temp, the name being anything before the colon, in this case it's "Test", and then I want to capitalize the name fully.
void func(char * temp) {
// where temp is a char * containing the string "Test:Case1"
char * name;
name = strtok(temp,":");
//convert it to uppercase
name = toupper(name); //error here
}
I'm getting the error that the function toupper() expects an int, but receives a char *. Thing is, I have to use char *s, since that is what the function is taking in, (I can't really use char arrays here, can I?).
Any help would be greatly appreciated.
toupper() converts a single char.
Simply use a loop:
void func(char * temp) {
char * name;
name = strtok(temp,":");
// Convert to upper case
char *s = name;
while (*s) {
*s = toupper((unsigned char) *s);
s++;
}
}
Detail: The standard Library function toupper(int) is defined for all unsigned char and EOF. Since char may be signed, convert to unsigned char.
Some OS's support a function call that does this: upstr() and strupr()
For those of you who want to uppercase a string and store it in a variable (that was what I was looking for when I read these answers).
#include <stdio.h> //<-- You need this to use printf.
#include <string.h> //<-- You need this to use string and strlen() function.
#include <ctype.h> //<-- You need this to use toupper() function.
int main(void)
{
string s = "I want to cast this"; //<-- Or you can ask to the user for a string.
unsigned long int s_len = strlen(s); //<-- getting the length of 's'.
//Defining an array of the same length as 's' to, temporarily, store the case change.
char s_up[s_len];
// Iterate over the source string (i.e. s) and cast the case changing.
for (int a = 0; a < s_len; a++)
{
// Storing the change: Use the temp array while casting to uppercase.
s_up[a] = toupper(s[a]);
}
// Assign the new array to your first variable name if you want to use the same as at the beginning
s = s_up;
printf("%s \n", s_up); //<-- If you want to see the change made.
}
Note: If you want to lowercase a string instead, change toupper(s[a]) to tolower(s[a]).
toupper() works only on a single character. But there is strupr() which is what you want for a pointer to a string.
How about this little function? It assumes ASCII represented chars and modifies string in place.
void to_upper(char* string)
{
const char OFFSET = 'a' - 'A';
while (*string)
{
*string = (*string >= 'a' && *string <= 'z') ? *string -= OFFSET : *string;
string++;
}
}
toupper() works on one element (int argument, value ranging the same as of unsigned char or EOF) at a time.
Prototype:
int toupper(int c);
You need to use a loop to supply one element at a time from your string.
I wrote a function that cuts all the left space of an inputted string. These two functions give the same output "haha" when input is " haha".
My question are:
1) Why the 1st one need return but the 2nd one doesn't. I added "return s" and it made a syntax error.
2) Are there any different in these if I use it in another situation?
3) Many said that 2nd one return a character not a string, how about my output ?
char *LTrim(char s[])
{
int i=0;
while(s[i]==' ')i++;
if (i>0) strcpy(&s[0],&s[i]);
return s;
}
and
char LTrim(char s[])
{
int i=0;
while(s[i]==' ')i++;
if (i>0) strcpy(&s[0],&s[i]);
}
This is my main():
int main()
{
char s[100];
printf("input string ");
gets(s);
LTrim(s);
puts(s);
return 0;
}
Your second code segment doesn't seem to have a return statement, please correct that for getting the correct answer.
The first function is returning a character pointer, which will be memory pointing to the starting location of your character array s, whereas the second function is returning a single character.
What you do with the values returned is what will make the difference, both the codes seem to be performing the same operation on the character array(string) passed to them, so if you are only looking at the initial and final string, it will be same.
On the other hand, if you actually use the returned value for some purpose, then you will get a different result for both functions.
char *LTrim(char s[]){} is a function of character array / string which returns character pointer i.e. returns reference / memory address.
While char LTrim(char s[]) is a function of character array / string, which return character only.
char is a single character.
char * is a pointer to a char.
char * are mostly used to point to the first character of a string (like sin your example).
In the first example you return your modified svariable, and in the second you return nothing so it's best to change the return value to void instead of char.
I'm trying to get input from the user while allocating it dynamically and then "split" it using strtok.
Main Questions:
Im getting an infinite loop of "a{\300_\377" and ",".
Why do i get a warning of "Implicitly declaring library function "malloc"/"realoc" with type void"
Other less important questions:
3.i want to break, if the input includes "-1", how do i check it? As you can see it breaks now if its 1.
4.In the getsWordsArray() i want to return a pointer to an array of strings. Since i dont know how many strings there are do i also need to dynamically allocate it like in the getInput(). (I dont know how many chars are there in each string)
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
char getInput()
{
char *data,*temp;
data=malloc(sizeof(char));
char c; /* c is the current character */
int i; /* i is the counter */
printf ("\n Enter chars and to finish push new line:\n");
for (i=0;;i++) {
c=getchar(); /* put input character into c */
if (c== '1') // need to find a way to change it to -1
break;
data[i]=c; /* put the character into the data array */
temp=realloc(data,(i+1)*sizeof(char)); /* give the pointer some memory */
if ( temp != NULL ) {
data=temp;
} else {
free(data);
printf("Error allocating memory!\n");
return 0 ;
}
}
printf("list is: %s\n",data); // for checking
return *data;
}
void getWordsArray(char *input)
{
char *token;
char *search = " ,";
token = strtok (input,search);
while (token != NULL ) {
printf("%s\n",token);
token = strtok(NULL,search);
}
}
EDIT:
i noticed i forgot to "strtok" command so i changed it to token = strtok(NULL,search);
I still get wierd output on the printf:
\327{\300_\377
Change:
int main(int argc, const char * argv[])
{
char input = getInput();
getWordsArray(&input);
}
to:
int main(int argc, const char * argv[])
{
char *input = getInput();
getWordsArray(input);
}
with a similar to the return value of getInput():
char *getInput()
{
// ...
return data;
}
In your code, you were only saving the first character of the input string, and then passing mostly garbage to getWordsArray().
For your malloc() question, man malloc starts with:
SYNOPSIS
#include <stdlib.h>
For your getchar() question, perhaps see I'm trying to understand getchar() != EOF, etc.
Joseph answered Q1.
Q2: malloc and realoc returns type void *. You need to explicitly convert that to char *. Try this:
data = (char *) malloc(sizeof(char));
Q3: 1 can be interpreted as one character. -1, while converting to characters, is equivalent to string "-1" which has character '-' and '1'. In order to check against -1, you need to use strcmp or strncmp to compare against the string "-1".
Q4: If you are going to return a different copy, yes, dynamically allocate memory is a good idea. Alternatively, you can put all pointers to each token into a data structure like a linked list for future reference. This way, you avoid making copies and just allow access to each token in the string.
Things that are wrong:
Strings in C are null-terminated. The %s argument to printf means "just keep printing characters until you hit a '\0'". Since you don't null-terminate data before printing it, printf is running off the end of data and just printing your heap (which happens to not contain any null bytes to stop it).
What headers did you #include? Missing <stdlib.h> is the most obvious reason for an implicit declaration of malloc.
getInput returns the first char of data by value. This is not what you want. (getWordsArray will never work. Also see 1.)
Suggestions:
Here's one idea for breaking on -1: if ((c == '1') && (data[i-1] == '-'))
To get an array of the strings you would indeed need a dynamic array of char *. You could either malloc a new string to copy each token that strtok returns, or just save each token directly as a pointer into input.
I have made strstr() function but the program does not give any output,just a blank screen.Please have a look at the code.
#include<stdio.h>
#include<conio.h>
const char* mystrstr(const char *str1, const char *str2);
int main()
{
const char *str1="chal bhai nikal";
const char *str2="nikal",*result;
result=mystrstr(str1,str2);
printf("found at %d location",(int*)*result);
getch();
return 0;
}
const char * mystrstr(const char *s1, const char *s2)
{
int i,j,k,len2,count=0;
char *p;
for(len2=0;*s2!='\0';len2++);//len2 becomes the length of s2
for(i=0,count=0;*s1!='\0';i++)
{
if(*(s1+i)==*s2)
{
for(j=i,k=0;*s2!='\0';j++,k++)
{
if(*(s1+j)==*(s2+i))
count++;
if(count==len2)
{
p=(char*)malloc(sizeof(char*));
*p='i';
return p;
}
}
}
}
return NULL;
}
The line with this comment:
//len2 becomes the length of s2
is broken. You repeatedly check the first character of s2. Instead of *s2, try s2[len2].
Edit: as others have said, there are apparently a lot more things wrong with this implementation. If you want the naive, brute-force strstr algorithm, here's a concise and fast version of it:
char *naive_strstr(const char *h, const char *n)
{
size_t i;
for (i=0; n[i] && h[i]; i++)
for (; n[i] != h[i]; h++) i=0;
return n[i] ? 0 : (char *)h;
}
It looks like this is an exercise you're doing to learn more about algorithms and C strings and pointers, so I won't solve those issues for you, but here are some starting points:
You have an infinite loop when calculating len2 (your loop condition is *s2 but you're never changing s2)
You have a similar issue with the second for loop, although I you have an early return so it might not be infinite, but I doubt the condition is correct
Given you want to behave like strstr(), you should return a pointer to the first string, not a new pointer you allocate. There is no reason for you to allocate during a function like strstr.
In main() if you want to calculate the position of the found string, you want to print result-str1 unless result is NULL). (int*)*result makes no sense - result should be a pointer to the string (or NULL)
You also need to change this line:
if(*(s1+j)==*(s2+i))
to this:
if(*(s1+j)==*(s2+k))
As already mentioned, the return value is a bit odd. You are returning a char* but kind of trying to put an integer value in it. The result doesn't make sense logically. You should either return a pointer to the location where it is found (no malloc needed) or return the integer position (i). But returning the integer position is not the "typical" strstr implementation.