Char to Int conversion in c - c

How can I convert a char to Int?
This is what I have done so far.
Thanks
scanf("%s", str );
printf("str: %s\n", str);
int i;
if(isdigit(*str))
i = (int) str;
else {
i = 3;
}
test case
7
str: 7
i: 1606415584

Edit: I could have sworn the post was tagged C++ at the start. I'll leave this up in case the OP is interested in C++ answers and the change to C tag was an edit.
A further option, which may be advanced given the question, is to use boost::lexical_cast as so:
scanf("%s", str );
printf("str: %s\n", str);
int i = boost::lexical_cast<int>( str );
I have used boost::lexical_cast a lot to convert between types, mostly strings and primitives when reading in user-defined properties. I find it an invaluable resource.
It's worth noting that boost::lexical_cast can throw exceptions, and these should be appropriately handled when you use the call. The link I posted at the start of this answer contains all the information you should need regarding that.

If you want to parse an integer from a string:
i = atoi(str);

You're mixing the character and string concepts here. str is a string, and str[0] (which is equivalent to *str) is a character, the first character of that string.
If you want to extract an integer from the string, try this
sscanf(str,"%d",&i);
Your
i = (int) str;
forces 4 bytes that start at the same memory address str (and for completeness sake, str is a pointer) starts to be interpreted as an integer, and that's why you get a result that's totally off.

You can convert strings to int by using sscanf
sscanf(str,"%d",&i);
http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/

i = (int) str;
is a wrong way to convert a string to number, because It copies an address to i variable (the address which str is pointing to it).
You could try this:
i = atoi(str);
or
sscanf(str,"%d",&i);
to convert your string into a number.
Note that you cannot make sure the entered string is numeric by just isdigit(*str), because it only check the first character of the string.
One possible way is this:
int isNumeric = 1;
for(int j=0;j<length(str);j++)
if( isdigit(str[j]) == false)
{
isNumeric = 0;
break;
}
if(isNumeric)
{
// Code when the string is number
// (e.g. convert the string to a number with atoi function)
}
else
{
// Code when the string is NOT number
// (e.g. show a error message)
}

Related

function returning a string of zeros in c

i trying to create a function that return an array of zeros us a char array
and print this array in a file text but when i return a string an addition char was returned
this the text file string the program wrote
this my fuction :
char *zeros_maker (int kj,int kj1)
{
char *zeros;
zeros = (char *) malloc(sizeof(char)*(kj-kj1));
int i;
for(i =0;i<kj-kj1;i++)
zeros[i]='0';
printf("%s\n",zeros);
return zeros;
}
the instruction i used when i printed in the file
fprintf(pFile,"%c%s%c &",34,zeros_maker(added_zeros,0),34);
Thanks in advance
'0' in C is the value of the encoding used for the digit zero. This is not allowed to have the value 0 by the C standard.
You need to add a NUL-terminator '\0' to the end of the char array, in order for the printf function to work correctly.
Else you run the risk of it running past the end of the char array, with undefined results.
Finally, don't forget to free the allocated memory at some point in your program.
Read about how string in C are meant to be terminated.
Each string terminates with the null char '\0' (the NULL symbol ASCII value 0, not to be confused with the char '0' that has ASCII value 48). It identifies the end of the string.
zeros[kj-kj1]='\0';
Plus check always if you are accessing an element out of bound. In this case it happens if kj1> kj
Instead of for loop, you may get hand of memset.
char* zeros_maker(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len-1);
zeros[len-1]=0;
printf("%s\n",zeros);
//fflush(stdout);
return zeros;
}
Or if you are not fan of C-style string, and it's going to be ASCII only, following could be used too. Just be careful what your are doing this way.
char* zeros_maker_pascal_form(int kj,int kj1)
{
int len=kj-kj1;
char *zeros=malloc(sizeof(char)*(len));
memset(zeros,'0',len);
for(int a=0;a<len;a++){
printf("%c",zeros[a]);
}
printf("\n");
//fflush(stdout);
return zeros;
}
Your code has a few basic issues, the main one is that it fails to terminate the string (and include space for the terminator).
Here's a fixed and cleaned-up version:
char * zeros_maker(size_t length)
{
char *s = malloc(length + 1);
if(s != NULL)
{
memset(s, '0', length);
s[length - 1] = '\0';
}
return s;
}
This has the following improvements over your code:
It simplifies the interface, just taking the number of zeroes that should be returned (the length of the returned string). Do the subtraction at the call site, where those two values make sense.
No cast of the return value from malloc(), and no scaling by sizeof (char) since I consider that pointless.
Check for NULL being returned by malloc() before using the memory.
Use memset() to set a range of bytes to a single value, that's a standard C function and much easier to know and verify than a custom loop.
Terminate the string, of course.
Call it like so:
char *zs = zeros_maker(kj - kj1);
puts(s);
free(s);
Remember to free() the string once you're done with it.

Check if a string is the substring of another string

I was having some problem when trying to check if a string is the substring of another string. Here is the expected output:
Enter a source string: abc
Enter the target string: abcde
findSubstring(): 1
Enter a source string: abcde
Enter the target string: cdef
findSubstring(): -1
And here is my code which used the strstr standard string library:
int main()
{
char sourceStr[40], targetStr[40];
printf("Enter a source string: ");
gets(sourceStr);
printf("Enter the target string: ");
gets(targetStr);
printf("findSubstring(): %d\n", findSubstring(sourceStr, targetStr));
return 0;
}
int findSubstring(char *s, char *t) {
if (strstr(s, t) != NULL) {
return 1;
}
return 0;
}
With these code, it works perfectly. However, I was told that I am not supposed to use any standard string library, so I was thinking how should I modify it?
Sorry for posting the question with no error but I seriously need a head start, as I googled for quite a while and I still have no idea how to do it.
Thanks in advance.
The key here is that when working in C, strings do not exist as an actual data structure as they do in, say, C++'s STL (std::string) or Java's String objects.
Instead, you should be treating them as a sequence of individual characters, whose end is denoted by an agreed-upon convention, which in this case is the 'NULL' character, which is the value 0 and can be represented in a string literal using the escaping symbol.
This is why strings are passed around as pointers to char in C, which actually point to the first character in the sequence.
Therefore, you can use pointer arithmetic to check the subsequent characters, until you find a value of 0, which means the string has ended.
By using a snippet like this, you can check any given string character by character.
char * pointer_to_string; //Pointer to start of string
char * pointer_to_character = pointer_to_string; //Start at the first character
while (*pointer_to_character != '\0'){ // Repeat while we haven't found the end
char c = *pointer_to_character; // The character the pointer is pointing to.
//do what you need to with the character
pointer_to_character++; //Now it points to the next character
}
// We exit the loop once the end of the string is found
HOWEVER:
This means you must be careful since this kind of string manipulation has its risks, since you are depending on finding an actual NULL character that ends the string, and if it's not present, the loop would run indefinitely, and in more complex examples, would easily lead to a segmentation fault and a crash.
In short, when using raw pointers in C, gotta be extra careful with what you do with the underlying memory, and certainly using known libraries and not reinventing the wheel tends to be the best option, but since I'm inclined to believe the purpose of the assignment is learning about string representation and pointer arithmetic, we'll do with that.
With this, you should be able to figure out what you need to do to solve the problem.
Well, if you don't want to use standard library, here is one way to do it.
This is simple code that satisfies the purpose:
int FindString(char *Str,const char *SubStr)
{
size_t count = 0 , x , y ;
size_t Str_len = strlen( Str ) ;
size_t SubStr_len = strlen( SubStr );
size_t diff = Str_len - SubStr_len;
if( SubStr_len > Str_len )
return 0;
for( x = 0 ; x <= diff ; x++ )
{
for( y = 0 ; y < SubStr_len ; y++ )
{
if( Str[ x + y ] == SubStr[ y ] )
count++;
else
{
count = 0;
break;
}
}
if( count == SubStr_len )
return 1;
}
return 0;
}
Also, if you want the version that compares insensitively, notify me in a comment.

Tokenizing a phone number in C

I'm trying to tokenize a phone number and split it into two arrays. It starts out in a string in the form of "(515) 555-5555". I'm looking to tokenize the area code, the first 3 digits, and the last 4 digits. The area code I would store in one array, and the other 7 digits in another one. Both arrays are to hold just the numbers themselves.
My code seems to work... sort of. The issue is when I print the two storage arrays, I find some quirks;
My array aCode; it stores the first 3 digits as I ask it to, but then it also prints some garbage values notched at the end. I walked through it in the debugger, and the array only stores what I'm asking it to store- the 515. So how come it's printing those garbage values? What gives?
My array aNum; I can append the tokens I need to the end of it, the only problem is I end up with an extra space at the front (which makes sense; I'm adding on to an empty array, ie adding on to empty space). I modify the code to only hold 7 variables just to mess around, I step into the debugger, and it tells me that the array holds and empty space and 6 of the digits I need- there's no room for the last one. Yet when I print it, the space AND all 7 digits are printed. How does that happen?
And how could I set up my strtok function so that it first copies the 3 digits before the "-", then appends to that the last 4 I need? All examples of tokenization I've seen utilize a while loop, which would mean I'd have to choose either strcat or strcpy to complete my task. I can set up an "if" statement to check for the size of the current token each time, but that seems too crude to me and I feel like there's a simpler method to this. Thanks all!
int main() {
char phoneNum[]= "(515) 555-5555";
char aCode[3];
char aNum[7];
char *numPtr;
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
printf("%s\n", aCode);
numPtr = strtok(&phoneNum[6], "-");
while (numPtr != NULL) {
strcat(aNum, numPtr);
numPtr = strtok(NULL, "-");
}
printf("%s", aNum);
}
I can primarily see two errors,
Being an array of 3 chars, aCode is not null-terminated here. Using it as an argument to %s format specifier in printf() invokes undefined behaviour. Same thing in a differrent way for aNum, too.
strcat() expects a null-terminated array for both the arguments. aNum is not null-terminated, when used for the first time, will result in UB, too. Always initialize your local variables.
Also, see other answers for a complete bug-free code.
The biggest problem in your code is undefined behavior: since you are reading a three-character constant into a three-character array, you have left no space for null terminator.
Since you are tokenizing a value in a very specific format of fixed length, you could get away with a very concise implementation that employs sscanf:
char *phoneNum = "(515) 555-5555";
char aCode[3+1];
char aNum[7+1];
sscanf(phoneNum, "(%3[0-9]) %3[0-9]-%4[0-9]", aCode, aNum, &aNum[3]);
printf("%s %s", aCode, aNum);
This solution passes the format (###) ###-#### directly to sscanf, and tells the function where each value needs to be placed. The only "trick" used above is passing &aNum[3] for the last argument, instructing sscanf to place data for the third segment into the same storage as the second segment, but starting at position 3.
Demo.
Your code has multiple issues
You allocate the wrong size for aCode, you should add 1 for the nul terminator byte and initialize the whole array to '\0' to ensure end of lines.
char aCode[4] = {'\0'};
You don't check if strtok() returns NULL.
numPtr = strtok(phoneNum, " ");
strncpy(aCode, &numPtr[1], 3);
Point 1, applies to aNum in strcat(aNum, numPtr) which will also fail because aNum is not yet initialized at the first call.
Subsequent calls to strtok() must have NULL as the first parameter, hence
numPtr = strtok(&phoneNum[6], "-");
is wrong, it should be
numPtr = strtok(NULL, "-");
Other answers have already mentioned the major issue, which is insufficient space in aCode and aNum for the terminating NUL character. The sscanf answer is also the cleanest for solving the problem, but given the restriction of using strtok, here's one possible solution to consider:
char phone_number[]= "(515) 555-1234";
char area[3+1] = "";
char digits[7+1] = "";
const char *separators = " (-)";
char *p = strtok(phone_number, separators);
if (p) {
int len = 0;
(void) snprintf(area, sizeof(area), "%s", p);
while (len < sizeof(digits) && (p = strtok(NULL, separators))) {
len += snprintf(digits + len, sizeof(digits) - len, "%s", p);
}
}
(void) printf("(%s) %s\n", area, digits);

Append to C String Based on User Input

I would like to receive an integer x via user input, and return a string with length x in '#'s.
i.e.
x = 4
⇒ "####"
Is a simple solution possible, along the lines of:
printf( "%c * x = %c", hash, x, hash*x);
Currently, my online findings have me creating an iterative program:
#include <stdio.h>
#include <string.h>
//function creates xhash with width '#' characters
void append( char* xhash, char hash, int x )
{
int i = 0;
for ( i = 0; i < x; i++ ) { xhash[i] = hash; }
xhash[x] = '\0';
}
int main ( void )
{
int x = 0;
scanf( "%d", &x );
char xhash[250] = "";
char hash = "#";
append( xhash, hash, x );
printf( "%c", xhash );
return 0;
}
And this gives me a strange design: ▒
I find C strings very confusing, coming from Python where I would use
str.append(i)
or
str = "#" * x
C does not have a full-fledged string data type. "C strings" are just contiguous sequences if char values, terminated by a character with value 0 (which can be spelled '\0').
Very important to your question, though, is that (1) char is an integer data type, (2) different delimiters are used for string literals than for (single-)char literals, and (3) string literals evaluate to pointers to the first character of a C string.
Thus, this ...
char hash = "#";
... attempts to store a pointer in hash, probably resulting in the last byte of the pointer value. Instead, you want this:
char hash = '#';
Moreover, to print a C string via one of the printf()-family functions, you want to use edit descriptor %s:
printf("%s", xhash);
Descriptor %c is for outputting a single character.
A string in C is just an array of bytes followed by a zero byte. That is all that they are.
For a function that creates a string you have two options. You can have the caller pass in a pointer to an array (and the array size, if you're smart) and the function fills it in. The second option is to malloc inside your function and return the pointer to the caller.
Another thing to remember is the standard C library. Your append function is essentially memset followed by setting a zero at the end. You should just call memset instead of doing your own loop.
And I think you are getting weird output because the printf format for a string is %s not %c. The %c format is for a single character.
Finally if you are unfamiliar with C programming you should be compiling will all warnings turned on. The compiler warnings would have told you about the bad printf format string and the invalid char assignment.

strcat() for formatted strings

I'm building a string piece by piece in my program and am currently using a mix of strcat() when I'm adding a simple string onto the end, but when im adding a formatted string I'm using sprintf() e.g.:
int one = 1;
sprintf(instruction + strlen(instruction), " number %d", one);
is it possible to concatenate formatted string using strcat() or what is the preferred method for this?
Your solution will work. Calling strlen is a bit awkward (particularly if the string gets quite long). sprintf() will return the length you have used [strcat won't], so one thing you can do is something like this:
char str[MAX_SIZE];
char *target = str;
target += sprintf(target, "%s", str_value);
target += sprintf(target, "somestuff %d", number);
if (something)
{
target += sprintf(target, "%s", str_value2);
}
else
{
target += sprintf(target, "%08x", num2);
}
I'm not sure strcat is much more efficient than sprintf() is when used in this way.
Edit: should write smaller examples...
no it's not possible but you could use sprintf() on those simple strings and avoid calling strlen() every time:
len = 0;
len += sprintf(buf+len, "%s", str);
len += sprintf(buf+len, " number %d", one);
To answer the direct question, sure, it's possible to use strcat to append formatted strings. You just have to build the formatted string first, and then you can use strcat to append it:
#include <stdio.h>
#include <string.h>
int main(void) {
char s[100];
char s1[20];
char s2[30];
int n = 42;
double x = 22.0/7.0;
strcpy(s, "n = ");
sprintf(s1, "%d", n);
strcat(s, s1);
strcat(s, ", x = ");
sprintf(s2, "%.6f", x);
strcat(s, s2);
puts(s);
return 0;
}
Output:
n = 42, x = 3.142857
But this is not a particularly good approach.
sprintf works just as well writing to the end of an existing string. See Mats's answer and mux's answer for examples. The individual arrays used to hold individual fields are not necessary, at least not in this case.
And since this code doesn't keep track of the end of the string, the performance is likely to be poor. strcat(s1, s2) first has to scan s1 to find the terminating '\0', and then copy the contents of s2 into it. The other answers avoid this by advancing an index or a pointer to keep track of the end of the string without having to recompute it.
Also, the code makes no effort to avoid buffer overruns. strncat() can do this, but it just truncates the string; it doesn't tell you that it was truncated. snprintf() is a good choice; it returns the number of characters that it would have written if enough space were available. If this exceeds the size you specify, then the string was truncated.
/* other declarations as above */
size_t count;
count = snprintf(s, sizeof s, "n = %d, x = %.6f", n, x);
if (count > sizeof s) {
/* the string was truncated */
}
And to append multiple strings (say, if some are appended conditionally or repeatedly), you can use the methods in the other answers to keep track of the end of the target string.
So yes, it's possible to append formatted strings with strcat(). It's just not likely to be a good idea.
What the preferred method is, depends on what you are willing to use. Instead of doing all those manual (and potentially dangerous) string operations, I would use the GString data structure from GLib or GLib's g_strdup_print function. For your problem, GString provides the g_string_append_printf function.
Write your own wrapper for your need.
A call to this would look like this :-
result = universal_concatenator(4,result,"numbers are %d %f\n",5,16.045);
result = universal_concatenator(2,result,"tail_string");
You could define one function, that would take care of worrying about, if you need to use sprintf() or strcat(). This is what the function would look like :-
/* you should pass the number of arguments
* make sure the second argument is a pointer to the result always
* if non formatted concatenation:
* call function with number_of_args = 2
* else
* call function with number of args according to format
* that is, if five inputs to sprintf(), then 5.
*
* NOTE : Here you make an assumption that result has been allocated enough memory to
* hold your concatenated string. This assumption holds true for strcat() or
* sprintf() of your previous implementation
*/
char* universal_concaternator(int number_of_args,...)
{
va_list args_list;
va_start(args_list,number_of_args);
int counter = number_of_args;
char *result = va_arg(args_list, char*);
char *format;
if(counter == 2) /* it is a non-formatted concatenation */
{
result = strcat(result,va_arg(args_list,char*));
va_end(args_list);
return result;
}
/* else part - here you perform formatted concatenation using sprintf*/
format = va_arg(args_list,char*);
vsprintf(result + strlen(result),format,args_list);
va_end(args_list);
return result;
}
/* dont forget to include the header
* <stdarg.h> #FOR-ANSI
* or <varargs.h> #FOR-UNIX
*/
It should firstly, determine, which of the two it should call(strcat or sprintf), then it should make the call, and make it easy for you to concentrate on the actual logic of whatever you are working on!
Just ctrl+c code above and ctrl+v into your code base.
Note : Matt's answer is a good alternative for long strings. But for short string lengths(<250), this should do.

Resources