How to separate character and number from string in c program - c

For example, I want to separate the string "0013subdivision" into 0013 (as an integer that can do addition, subtraction, etc. not char) and subdivision (as a char itself) in the given string.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
char location[10]; /* for the input with number and letter */
char x;
int house[10]; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
scanf ("%s", &location[x]);
x=0
for (x=0; location[x]!='\0'; x++ );
return 0;
}
Based on my research, the code atoi is used to convert the converted value back to int (if I'm not mistaken) but I don't know when to place the function.

location is char array, if you are reading as string use only %s with string name only, index not required.
scanf ("%s", &location[x]); --> scanf ("%s", location);
After separating only int from char array you need to store one int value into house.
int house[10] --> int house.
Here is the code for extracting only int from string :
char location[10]; /* for the input with number and letter */
int x;
int house = 0 ; /* for the integer that will be separated from the string */
int main()
{
printf("Input: ");
//scanf ("%s", &location[x]);
scanf ("%s", location);
for (x=0; location[x]!='\0'; x++ ) {
if(location[x]>='0' && location[x]<='9') {
house =(house * 10) + (location[x]-48);
}
}
printf("int part = %d \n",house);
return 0;
}

The main problem in the code is
scanf ("%s", &location[x]);
Where you did not impose any limit on the scanning. An input like 0013subdivision will cause out of bound memory access leading to undefined behavior.
Always limit the input size with the length modifier, like, for an array defined as
char location[10]
use the conversion specification like
scanf ("%9s", location); // (i) one element saved for terminating null
// (ii) the array name decays to the pointer to 1st element
//in case of an argument to a function call.
Then, you don't need an integer array to store the extracted integer. A singular variable would suffice.
However, i'd like to suggest a much robust way:
read the user input using fgets()
then, scan the input using sscanf() and appropriate conversion specifier, like %4d%9s or alike.

The most correct way to do this is to use the strto... family of functions from stdlib.h. For example:
printf("%ld\n", strtol(str, NULL, 10));
The atoi family of functions should never be used for any purpose, since they have broken error handling and can be 100% replaced by the strto... functions.
You could use the scanf family of functions but they are needlessly slow and notoriously dangerous, so I don't really see the point of using them here.
If you are interested in implementing the actual copying manually, for learning purposes, it is fairly trivial:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
const char str[] = "0013subdivision";
char number_part [sizeof(str)];
char letter_part [sizeof(str)];
size_t i;
for(i=0; str[i]!='\0' && isdigit(str[i]); i++) // find where the letters start
{}
memcpy(number_part, &str[0], i); // copy digit part
number_part[i] = '\0'; // append null terminator
memcpy(letter_part, &str[i], sizeof(str)-i); // copy letter part + null term
puts(number_part);
puts(letter_part);
printf("%ld\n", strtol(str, NULL, 10));
}
If the string is a run-time variable, you have to use strlen(str)+1 instead of sizeof().

strtol converts string to number and also gives you back the character it stopped on, i.e. first character after number.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char* const input = "0013subdivision";
const char* string;
const long number = strtol(input, &string, 10);
printf("Number: %ld String: '%s'\n", number, string);
// Number: 13 String: 'subdivision'
return 0;
}
https://repl.it/repls/SphericalImpracticalTinamou

Related

How can I scan a string with unknown size and values to use inside a function in C using gets()?

I am trying to convert a number from base b to base 10 using the function base_b_to_10 as below:
long int base_b_to_10(char* B, long int base) //take in the number as string returns it converted to base 10 as long int
{
long int N; //base 10 number:
N = strtol(B, NULL, base); //
return(N);
}
In the main program, the user will input the base of the input number and the input number itself.
The length and the size of the string is unknown and is up to the user to define
This is a simplified version of a big program I am trying to build in which the size of the string B is dynamically allocated in another function so I cannot do something like:
char B[100];
How to solve this? the compiler is returning nothing.
Input string (here: test) can be of any reasonable size. Anyway, there might be some limitations, see: Strtol() and atol() do not convert strings larger than 9 digits
Output string is a pointer (here: *str) to position within input string (here: test). According to this, the size of the string to which str points does not matter. (Note: In this example, str is only valid as long as test is valid).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long int base_b_to_10(char* B, long int base, char **ret_str)
{
long int N;
N = strtol(B, ret_str, base);
return N;
}
int main()
{
long int val;
char *str;
char test[50] = "43724325HelloWorld";
val = base_b_to_10(test, 10, &str);
printf("val = %ld\n", val);
printf("str = %s\n", str);
return 1;
}
Notes: I adapted your example just to be working (not improving or simplifying anything). It is probably clear that you could also directly use strtol function in the main routine. Moreover, it does not matter, how the input string was allocated (fixed size or dynamic size) - just needs to be allocated and needs to end by \0 (as usual).
If cross platforming is not an issue, and assuming you are running on a linux system, you can make use of asprintf().
It basically formats your string and allocates the memory for you (remember to free it afterwards).
This is not part of the standard library so it has its limitations.
Another approach is to use snprintf() to preddict the size of the output buffer then and use malloc()
#include <stdio.h>
int main ()
{
int cx = snprintf ( NULL, 0, "18 characters long" );
printf("%d", cx);
return 0;
}
// OUTPUT:
// 18
Ok so I solved this problem by first using a buffer string with size 50 (pretty sufficient), than I used the strlen() function to determine the size of the string given by the user, and lastly I allocate this number to the string I will be using for the conversion:
char *str, buffer[50];
printf("enter the input value: ");
gets(buffer);
int i;
i = strlen(buffer);
str = (char*)malloc(i*sizeof(char));
strcpy(str, buffer);
fflush(stdin);
N = base_b_to_10(str, base_in);

Not able to take string and float as input in a single line in C

What I have till now is this. I am not able to figure out how to take the input as mentioned and solve this problem?
#include<stdio.h>
#include <stdlib.h>
#include<float.h>
int main()
{
char s[50];
float mil,min=FLT_MAX;
while(scanf("%s#%f",s,&mil)!=-1)
{
printf("%s\n",s);
if(mil<min)
min=mil;
}
}
EDIT: My problem is that when I print the string s inside the loop, "Zantro#16.15" is printed whereas I want only "Zantro" to be stored in s and 16.15 to be stored in mil
%s scans up until a whitespace. Scan up until a # instead.
while (scanf("%[^#]#%f", s, &mil) == 2)
Remember to specify the maximum buffer size in the scanning format to protect against overflows:
while (scanf("%49[^#]#%f", s, &mil) == 2)
Well the scanf function can not easily determine, that you want the # sign to be a delimiter. Therefore you need to add an extra step to split up the strings into proper parts and store them for later comparison.
Have a look at strtok function in c.
http://www.c-howto.de/tutorial/strings-zeichenketten/string-funktionen/string-zerteilen/
Here is a solution that prints the requested string:
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main()
{
char s[50];
char mins[50];
float mil,min=FLT_MAX;
int rc;
int done=0;
while (done == 0)
{
rc = scanf("%49[^#]#%f", s, &mil);
if (rc != 2)
{
done = 1;
continue;
}
if (mil < min)
{
min = mil;
strcpy(mins, s);
}
}
printf("%s\n", mins);
return 0;
}
Execution:
./sc
Zantro#16.15
Zirty#12.5
Gamry#9.8
Gamry
#include<stdio.h>
#include <stdlib.h>
#include<float.h>
int main()
{
char s[50];
float mil, min = FLT_MAX;
while (scanf("%[^#]#%f", s, &mil) == 2)
{
printf("%s\n", s);
if (mil < min)
min = mil;
}
}
Input:Zantro#16.15Zity#12.5Gamry#9.8
OutPut:
Zantro
Zity
Gamry
If you want to split your input in the scanf to string and float, you have to write those two types separately. For example, ("%s %f"). This string tells the function, what will be the arguments types. Therefore, if you write it like this ("%s#%f") the scanf function has a problem to understand, what will be the inputs types. In addition, if you write ("%s #%f") it will get two inputs like this " #". Your problem here is the space between the two arguments. Because, I didnt find how to get the input without this space. I'm recommending you to try splitting the input in another way.
For example, take one string that holds the intaier input to string buffer-> scanf("%s",sBuffer).
and split that to different variables after that.

Getting an infinite running program when using scanf

I'm getting an infinite running programm when I use the following code to read a string from keyboard and save it within a structured vector.
scanf("%s", strk_zgr_fp->bezeichnung, (int)sizeof(strk_zgr_fp->bezeichnung - 1));
Simply nothing happens after this line is reached and the program runs infinitly.
I know scanf() isn't recommended. We're using it only within our C beginners course and I want you to keep it in mind, ie please don't recommend other function rather than above mentioned for the moment.
Any help is much appreciated, thanks in advance.
#include <stdio.h>
typedef struct {
int nummer;
char bezeichnung;
int menge;
float preis;
} artikel;
void eingabe_artikel(artikel *strk_zgr_fp, int i_fp);
void ausgabe_artikel(artikel *strk_zgr_fp, int i_fp);
void main(void) {
artikel artikelliste[10];
artikel *strk_zgr;
int anzahl;
do {
printf("Bitte eine #Artikel eingeben [<= 10]: ");
scanf("%d", &anzahl);
if(anzahl < 1 || 10 < anzahl)
printf("\nEs wurde eine falsche #Artikel eingegeben.");
} while(anzahl < 1 || 10 < anzahl);
for(int i = 0; i < anzahl; i++)
eingabe_artikel(&artikelliste[i], i);
int i;
for(strk_zgr = artikelliste, i = 0; strk_zgr < artikelliste + anzahl;
strk_zgr++, i++)
ausgabe_artikel(strk_zgr, i);
}
void eingabe_artikel(artikel *strk_zgr_fp, int i_fp) {
printf("\nBitte den %d. Artikel eingeben: ", ++i_fp);
printf("\nNummer: ");
scanf("%d", &strk_zgr_fp->nummer);
printf("Bezeichnung: );
scanf("%s", strk_zgr_fp, (int)sizeof(strk_zgr_fp->bezeichnung - 1)); /* <-- */
printf("Menge: ");
scanf("%d", &strk_zgr_fp->menge);
float preis;
printf("Preis: );
scanf("%f", &preis);
strk_zgr_fp->preis = preis;
}
void ausgabe_artikel(artikel *strk_zgr_fp, int i_fp) {
printf("\n%d. Artikel: ", ++i_fp);
printf("\nNummer:\t%d", strk_zgr_fp->nummer);
printf("\nBezeichnung:\t%s", strk_zgr_fp->bezeichnung);
printf("\nMenge:\t%d", strk_zgr_fp->menge);
printf("\nPreis:\t%.2f EUR\n", strk_zgr_fp->preis);
}
NetBeans Version
Complier Version
Many problems in the code. Please at least fix the missing ending quotes on the printf() calls.
Now to the beef:
1) Your structure is wrong. 'Bezeichnung' is defined as a single character, not a string.
typedef struct {
int nummer;
char bezeichnung[100];
int menge;
float preis;
} artikel;
2) You cannot use scanf() in the way you did. If you want to limit the input length (which always is a good idea), you need to pass the maximum length into the format string.
Do you nee to use scanf()?? Because it gets messy from here on....
As your maximum input length might be variable or subject to change (see 1.), you need to build the format string for scanf. Something like this:
char format_str[15];
format_str[0] = '%';
//Dont use itoa(), it is not C standard.
sprintf(&format_str[1], "%d", (int)sizeof(strk_zgr_fp->bezeichnung) - 1);
strcat(format_str, "s");
scanf(format_str, strk_zgr_fp->bezeichnung);
Hope that gets you going.
PS: You need to include string.h for strcat().
I tried it out and it worked fine for me. Not sure on this sprintf() function. Could you please explain why I'm supposed to use it? By now, I used this code: char format_str[20]; format_str[0] = '%'; strcat(format_str, "s"); printf("Bezeichnung: "); scanf(format_str, strk_zgr_fp->bezeichnung);
While that works, you are missing out on limiting the length of the user's input. That is why I proposed using sprintf() to create a (sub)string containing the maximal allowable length of the user input, depending on how large your 'bezeichnung' is defined in the struct. Suppose 'bezeichnung' has a limit of 100 characters, you would want to limit the input to 99 (+1 for the zero-termination), so you want a scanf format string like this: "%99s".
chux has provided a much more compact version of my three lines, but I think, in the beginning, you will have it easier to just assemble such format strings piece by piece, at the same time learning how to a) change individual characters in a string, how to use sprintf() in a basic way, and how to concatenate strings with strcat().
There was another example which I did and the course leader provided a scanf() function like this to read a string: scanf("%s", &(strk_zgr_fp->bezeichnung));. I thought when I'm reading a string the address operator isn't used. The only difference is the address operator now is used and the element was put into brackets.
Now, I think this is bad practice. It works, but is superfluous. Consider this small code snippet:
#include <stdio.h>
#include <stdlib.h>
struct test{
int i;
char a_str[10];
};
int main()
{
struct test a_test;
printf("Normal array adress taking: %p\n", a_test.a_str);
printf("Using '&' to take adress of array: %p\n", &(a_test.a_str));
return 0;
}
Hope that helps.

how to print a string in c without pā” in the end of the string

so i've been writing a program that convert a decimal number to it's boolean representation but every time i compile the return value which is a string show additional characters like pā” here is the program
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main (void)
{
signed char str[256];
int dec,rest;
int i = -1;
int j;
printf ("write a decimal number : ");
scanf ("%d",&dec);
do
{
rest = dec % 2;
dec/= 2;
for (j=i;j>-1;--j)
str[j+1]=str[j];
str[0]=rest+48;
++i;
} while (dec!=0);
printf ("the binary representation of this number is %s",str);
}
the output :
write a decimal number : 156
the binary representation of this number is 10011100pā”
i don't know if im missing something but i will be grateful if you guys help me
In C and C++, strings are null-terminated, this means that every valid string must end with a character with code 0. This character tells every function that is dealing with this string that it is in fact over.
In your program you create a string, signed char str[256]; and it is initially filled with random data; this means that you reserved space for 256 characters and they are all garbage, but the system does not know they are invalid. Try printing this string and see what happens.
In order to actually tell the system that your string is over after say, 8 characters, the 9th character hast to be the NUL character, or simply 0. In your code you can do it in two ways:
after the loop, assign str[i] = 0, or (even simpler)
initialize the string as signed char str[256]={0};, whiche creates the storage and fills it with nulls; after writing to the string you can be sure that the character after the last one you've written will be a NUL.
At the end of your do {} while () loop, you need to set the character after the last character in your string to 0. This is the array index of the last character you want (i) plus one. This lets printf know where your string ends. (Otherwise, how could it know?)
initialize the str variable to NUL.
void main (void)
{
signed char str[256];
int dec,rest;
int i = -1;
int j;
memset( str, '\0', sizeof(str) );
printf ("write a decimal number : ");
scanf ("%d",&dec);
do
{
rest = dec % 2;
dec/= 2;
for (j=i;j>-1;--j)
str[j+1]=str[j];
str[0]=rest+48;
++i;
} while (dec!=0);
printf ("the binary representation of this number is %s",str);
}

How to correctly input a string in C

I am currently learning C, and so I wanted to make a program that asks the user to input a string and to output the number of characters that were entered, the code compiles fine, when I enter just 1 character it does fine, but when I enter 2 or more characters, no matter what number of character I enter, it will always say there is just one character and crashes after that. This is my code and I can't figure out what is wrong.
int main(void)
{
int siz;
char i[] = "";
printf("Enter a string.\n");
scanf("%s", i);
siz = sizeof(i)/sizeof(char);
printf("%d", siz);
getch();
return 0;
}
I am currently learning to program, so if there is a way to do it using the same scanf() function I will appreciate that since I haven't learned how to use any other function and probably won't understand how it works.
Please, FORGET that scanf exists. The problem you are running into, whilst caused mostly by your understandable inexperience, will continue to BITE you even when you have experience - until you stop.
Here is why:
scanf will read the input, and put the result in the char buffer you provided. However, it will make no check to make sure there is enough space. If it needs more space than you provided, it will overwrite other memory locations - often with disastrous consequences.
A safer method uses fgets - this is a function that does broadly the same thing as scanf, but it will only read in as many characters as you created space for (or: as you say you created space for).
Other observation: sizeof can only evaluate the size known at compile time : the number of bytes taken by a primitive type (int, double, etc) or size of a fixed array (like int i[100];). It cannot be used to determine the size during the program (if the "size" is a thing that changes).
Your program would look like this:
#include <stdio.h>
#include <string.h>
#define BUFLEN 100 // your buffer length
int main(void) // <<< for correctness, include 'void'
{
int siz;
char i[BUFLEN]; // <<< now you have space for a 99 character string plus the '\0'
printf("Enter a string.\n");
fgets(i, BUFLEN, stdin); // read the input, copy the first BUFLEN characters to i
siz = sizeof(i)/sizeof(char); // it turns out that this will give you the answer BUFLEN
// probably not what you wanted. 'sizeof' gives size of array in
// this case, not size of string
// also not
siz = strlen(i) - 1; // strlen is a function that is declared in string.h
// it produces the string length
// subtract 1 if you don't want to count \n
printf("The string length is %d\n", siz); // don't just print the number, say what it is
// and end with a newline: \n
printf("hit <return> to exit program\n"); // tell user what to do next!
getc(stdin);
return 0;
}
I hope this helps.
update you asked the reasonable follow-up question: "how do I know the string was too long".
See this code snippet for inspiration:
#include <stdio.h>
#include <string.h>
#define N 50
int main(void) {
char a[N];
char *b;
printf("enter a string:\n");
b = fgets(a, N, stdin);
if(b == NULL) {
printf("an error occurred reading input!\n"); // can't think how this would happen...
return 0;
}
if (strlen(a) == N-1 && a[N-2] != '\n') { // used all space, didn't get to end of line
printf("string is too long!\n");
}
else {
printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
}
}
Remember that when you have space for N characters, the last character (at location N-1) must be a '\0' and since fgets includes the '\n' the largest string you can input is really N-2 characters long.
This line:
char i[] = "";
is equivalent to:
char i[1] = {'\0'};
The array i has only one element, the program crashes because of buffer overflow.
I suggest you using fgets() to replace scanf() like this:
#include <stdio.h>
#define MAX_LEN 1024
int main(void)
{
char line[MAX_LEN];
if (fgets(line, sizeof(line), stdin) != NULL)
printf("%zu\n", strlen(line) - 1);
return 0;
}
The length is decremented by 1 because fgets() would store the new line character at the end.
The problem is here:
char i[] = "";
You are essentially creating a char array with a size of 1 due to setting it equal to "";
Instead, use a buffer with a larger size:
char i[128]; /* You can also malloc space if you desire. */
scanf("%s", i);
See the link below to a similar question if you want to include spaces in your input string. There is also some good input there regarding scanf alternatives.
How do you allow spaces to be entered using scanf?
That's because char i[] = ""; is actually an one element array.
Strings in C are stored as the text which ends with \0 (char of value 0). You should use bigger buffer as others said, for example:
char i[100];
scanf("%s", i);
Then, when calculating length of this string you need to search for the \0 char.
int length = 0;
while (i[length] != '\0')
{
length++;
}
After running this code length contains length of the specified input.
You need to allocate space where it will put the input data. In your program, you can allocate space like:
char i[] = " ";
Which will be ok. But, using malloc is better. Check out the man pages.

Resources