How to read multiple digit number from a string - c

I am trying to pass a string S as input. Here the string S can contain multiple integer values followed by an alphabet. The program must expand the alphabets based on the previous integer value.
Consider the Input: 4a5h
For which the Output: aaaahhhhh, that is 4 times a and 5 times h
Also for Input: 10a2b
Output: aaaaaaaaaabb, that is 10 times a and 2 times b
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char s[1000], alp[1000];
int num[1000];
int n = 0;
int i, j, k, m;
k = 0;
scanf("%[^\n]s", s);//Reads string until newline character is encountered
for (i = 0; i < strlen(s); i++) {
if (isalpha(s[i])) {
alp[n] = s[i]; // alp[] stores the alphabets
n += 1;
} else {
num[k] = s[i] - '0';// num[] stores the numbers
k += 1;
}
}
for (i = 0; i < k; i++) {
for (m = 0; m < num[i]; m++)
printf("%c", alp[i]);
}
return 0;
}
But with this code I am not able to read 2 or 3 or a N digit number. So if the Input is 100q1z then the alp[] array is fine but num[] array is not containing 100 and 1 as its elements instead 1 and 0 are its elements.
How do I correct this code?

You should modify the loop to handle as many digits are present successively int the string:
#include <ctype.h>
#include <stdio.h>
int main(void) {
char s[1000], alp[1000];
int num[1000];
int i, k = 0, m, n;
//Read string until newline character is encountered
if (scanf("%999[^\n]", s) == 1) {
for (i = 0; s[i]; i++) {
n = 1;
if (isdigit((unsigned char)s[i])) {
for (n = s[i++] - '0'; isdigit((unsigned char)s[i]); i++) {
n = n * 10 + s[i] - '0';
}
}
if (isalpha((unsigned char)s[i])) {
alp[k] = s[i]; // store the letter
num[k] = n; // store the number
k += 1;
}
}
for (i = 0; i < k; i++) {
for (m = 0; m < num[i]; m++)
putchar(alp[i]);
}
}
putchar('\n');
return 0;
}
Notes:
include <ctype.h> to use isalpha().
protect the destination array of scanf by passing a maximum number of characters and check the return value.
the format for converting a non empty line is simply %[^\n], the trailing s is incorrect. Note that unlike fgets(), this scanf() format will fail if the line is empty.
you should always test the return value of scanf().
cast the char argument to isalpha() and isdigit() as (unsigned char) to avoid undefined behavior if char is signed and has a negative value.
use putchar(c) to output a single character instead of printf("%c", c);

The part of else-bolock must be looped.
like this
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> //need this for isalpha and isdigit
int main(void){
char s[1000], alp[1000];
int num[1000];
int m = 0, n = 0;
int i, j;
unsigned char ch;//convert char to unsigned char before use isalpha and isdigit
scanf("%999[^\n]", s);//remove s after [^\n] and Add limit
for(i = 0; ch = s[i]; i++){//replace strlen each loop
if(isalpha(ch)){
alp[n++] = s[i];
} else if(isdigit(ch)){
num[m] = 0;
while(isdigit(ch = s[i])){
num[m] = num[m] * 10 + s[i] - '0';
++i;
}
++m;
--i;//for ++i of for-loop
} else {//Insufficient as validation
printf("include invalid character (%c).\n", ch);
return -1;
}
}
for(i = 0; i < m; i++){
for(j = 0; j < num[i]; j++)
printf("%c", alp[i]);
}
puts("");
return 0;
}

The problem with the code is that when you encounter a digit in the string, you are considering it as a number and storing it in num array. This is fine if you have only single digit numbers in the array. For multidigit numbers do this- read the string for digits until you find a alphabet, form a number using the obtained digits and then save it to num array.I m leaving the code for you.

Related

printing * corresponding to the number of iteration

So in C I'm supposed to let the user input an integer n from the interval [5, 25]. And then, for every number from 1 to n, in a new line print that many stars so it would look something like this:
*
**
***
I tried doing it like this, but it's not working. What am I doing wrong here?
#include <stdio.h>
int main(void)
{
int n, i;
char star = '*';
do {
printf("Input an int from [5, 25]");
scanf("%d", &n);
} while (n < 5 || n >= 25);
for (i=0; i < n; i++){
star += '*';
printf("%c", star);
}
return 0;
}
You cannot write star += '*'; because you declared star as a char, C is strongly typed, a char is a char not a table of char.
You have to use nested loop, like this for example:
#include <stdio.h>
int main(void)
{
int n, i, j;
char star = '*';
do
{
printf("Input an int from [5, 25]");
scanf("%d", &n);
} while (n < 5 || n >= 25);
for (i = 1; i <= n; i++)
{
for (j = 1; j <= i; j++)
{
printf("*");
}
printf("\n");
}
return 0;
}
You need nested loops
for (int i=0; i < n; i++)
{
for(int j = 0; j <= i; j++)
printf("*");
printf("\n");
}
or if you want to use strings:
char str[n + 1];
for (int i=0; i < n; i++)
{
str[i] = '*';
str[i + 1] = 0;
puts(str);
}
https://godbolt.org/z/aT8brP1ch
The statement
star += '*';
is not the correct way to concatenate two strings in C. In order to do this, you can define an array with sufficient space for the string and use the function strcat, like this:
#include <stdio.h>
#include <string.h>
int main(void)
{
int n;
//initialize "stars" to an empty string
char stars[20] = {0};
do {
printf("Input an int from [5, 25]: ");
scanf("%d", &n);
} while (n < 5 || n >= 25);
//build the string containing the stars using repeated
//string concatentation
for ( int i = 0; i < n; i++ ) {
strcat( stars, "*" );
}
//print the string
printf( "%s\n", stars );
return 0;
}
This program has the following behavior:
Input an int from [5, 25]: 5
*****
However, this is highly inefficient and unnecessarily complicated. Instead of first building the string in an array before printing it out all at once, it is usually easier to simply print it one character at a time:
#include <stdio.h>
#include <string.h>
int main(void)
{
int n;
do {
printf("Input an int from [5, 25]: ");
scanf("%d", &n);
} while (n < 5 || n >= 25);
//print the stars one character at a time
for ( int i = 0; i < n; i++ ) {
putchar( '*' );
}
//end the line
putchar( '\n' );
return 0;
}
This program has the same output as the first program.
You now have the solution for printing out a single line. However, your task involves printing out several lines. This will require a nested loop. In accordance with the community guidelines on homework questions, I will not provide the full solution at this time, as you should attempt to do this yourself, first.
char is an integral type - that is, it represents a number. '*' is a Character Constant, which actually has the type int.
char star = '*';
star += '*';
In ASCII, this is no different from
char star = 42;
star += 42;
A string is a series of nonzero bytes, followed by a zero byte (the null terminating character, '\0'). You cannot build a string by adding two integers together.
To build a string, you must place each byte in a buffer in sequence, and ensure a null terminating byte follows.
#include <stdio.h>
#define MIN 5
#define MAX 25
int main(void)
{
int n;
do {
printf("Input an int from [%d, %d): ", MIN, MAX);
if (1 != scanf("%d", &n)) {
fprintf(stderr, "Failed to parse input.\n");
return 1;
}
} while (n < MIN || n >= MAX);
char buffer[MAX + 1] = { 0 };
for (int i = 0; i < n; i++) {
buffer[i] = '*';
buffer[i + 1] = '\0';
puts(buffer);
}
}
Aside: never ignore the return value of scanf.
Or you can avoids strings, and just print the characters directly.
for (int i = 0; i < n; i++) {
for (int j = 0; j <= i; j++)
putchar('*');
putchar('\n');
}
#include <stdio.h>
#include <stdlib.h>
int main() {
int n,i,j;
printf("enter a number between 5 & 25");
scanf("%d",&n);
for(i=1;i<=n;i++){
for(j=1;j<=i;j++){
printf("*");
}
printf("\n");
}
return 0;
}
String concatenation does not work like that in C, instead use strcat().

Word finder not outputting as expected

the code is supposed to output all possible word combinations without any whitespace but with this method, it gives me whitespace
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char letters[6];
int on = 0;
int results;
printf("input the words all together: ");
scanf("%s", letters);
if (strlen(letters) == 6) {
for (int i = 0; i <= 6; i++) {
for (int j = 0; j <= 6; j++) {
for (int k = 0; k <= 6; k++) {
for (int l = 0; l <= 6; l++) {
for (int m = 0; m <= 6; m++) {
for (int n = 0; n <= 6; n++) {
char wordNow[6] = {
letters[i],
letters[j],
letters[k],
letters[l],
letters[m],
letters[n]
};
printf("%s\n", wordNow);
results = results+1;
}
}
}
}
}
}
}
printf("%d", results);
return 0;
}
This code is supposed to take in 6 characters and produce all possible combinations using those characters. When I use that method, the combinations end up repeating and gives me whitespace.
My old method that works but adds whitespace is:
printf("%c %c %c %c %c %c\n",
letters[i], letters[j], letters[k],
letters[l], letters[m], letters[n]);
If anyone could help, I would appreciate it.
wordNow is not null terminated, leading to the output you are seeing. Also, results is not initialized.
You'll need to null terminate your string if you plan to print it, since printf will keep iterating over the characters in the string until it hits the null terminator:
char wordNow[7] = {
letters[i],
letters[j],
letters[k],
letters[l],
letters[m],
letters[n],
'\0' // <-- added
};
int results; should be int result = 0; as Brady points out.
You might want to run your loops up to < rather than <= if you want to omit null terminators.

How do I compare an integer with a character in a string in C?

I want to compare the integers in a string with integers (0-9) and I wrote this -
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main() {
char num[100];
int count = 0;
scanf("%s", num);
int len = strlen(num);
for (int i = 0; i <= 9; i++)
{
for (int j = 0; j <= len; j++)
{
if (i == (num[j] - '0'))
{
count++;
}
}
printf("%d ", count);
count = 0;
}
return 0;
}
No problems with this (works in most cases but it is failing in few cases). So can you please give me alternate and best idea to do this?
Thanks in advance
Complete pic -
The root cause is not in char comparison, but in the under-allocated buffer:
char num[100];
The assignment constraint is:
1 <= len(num) <= 1000
After increasing the buffer size, all the tests pass.
Besides a too small input buffer (i.e. 100 instead of 1001), I think your approach is too complex.
Instead of a nested loop, I'll suggest an array to count the frequency, i.e. an array with 10 elements so that you have a counter for each digit.
int main() {
char num[1001]; // 1000 chars + 1 zero termination
int count[10] = {0}; // Array of 10 zero initialized counters, one for each digit
scanf("%1000s", num); // At max accept 1000 chars input
char* p = num;
while (*p)
{
if (isdigit(*p) ++count[*p - '0'];
++p;
}
for (int i = 0; i < 10; ++i) printf("%d ", count[i]);
puts("");
return 0;
}
If you don't want to use isdigit you can instead do:
if (*p >= '0' && *p <= '9') ++count[*p - '0'];

scan n numbers without spaces in C

Suppose n numbers are to be input in a single line without any spaces given the condition that these numbers are subject to the condition that they lie between 1 and 10.
Say n is 6 , then let the input be like "239435"
then if I have an array in which I am storing these numbers then I should get
array[0]=2
array[1]=3
array[2]=9
array[3]=4
array[4]=3
I can get the above result by using array[0]=(input/10^n) and then the next digit
but is there a simpler way to do it?
Just subtract the ASCII code of 0 for each digit and you get the value of it.
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i;
for(i = 0; i < l; i++)
array[i] = s[i]-'0';
update
Assuming that 0 is not a valid input and only numbers between 1-10 are allowed:
char *s = "239435"
int l = strlen(s);
int *array = malloc(sizeof(int)*l);
int i = 0;
while(*s != 0)
{
if(!isdigit(*s))
{
// error, the user entered something else
}
int v = array[i] = *s -'0';
// If the digit is '0' it should have been '10' and the previous number
// has to be adjusted, as it would be '1'. The '0' characater is skipped.
if(v == 0)
{
if(i == 0)
{
// Error, first digit was '0'
}
// Check if an input was something like '23407'
if(array[i-1] != 1)
{
// Error, invalid number
}
array[i-1] = 10;
}
else
array[i] = v;
s++;
}
E.g.
int a[6];
printf(">");
scanf("%1d%1d%1d%1d%1d%1d", a,a+1,a+2,a+3,a+4,a+5);
printf("%d,%d,%d,%d,%d,%d\n", a[0],a[1],a[2],a[3],a[4],a[5]);
result:
>239435
2,3,9,4,3,5
You can use a string to take the input and then check each position and extact them and store in an array. You need to check for the numeric value in each location explicitly, as you are accepting the input as a string. For integers taken input as string, there's no gurantee that the input is pure numeric and if it is not, things can go wild.
check this code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char ipstring[64];
int arr[64];
int count, len = 0;
printf("Enter the numbersi[not more than 64 numbers]\n");
scanf("%s", ipstring);
len = strlen(ipstring);
for (count = 0; count < len ; count++)
{
if (('0'<= ipstring[count]) && (ipstring[count] <= '9'))
{
arr[count] = ipstring[count] - '0';
}
else
{
printf("Invalid input detectde in position %d of %s\n", count+1, ipstring );
exit(-1);
}
}
//display
for (count = 0; count < len ; count++)
{
printf("arr[%d] = %d\n", count, arr[count]);
}
return 0;
}

Using getchar() to store a value to compare with an integer

i'm trying to count how many times a user inputs a certain digit and assign total number of instances to a location in a 10 row array (0-9). For instance if the user inputs 888, it will assign 3 to location arr1[8].
#include <stdio.h>
#include <stdlib.h>
int main(void){
int arr1[10] = {0};
int c;
while ((c = getchar()) != '\n'){
for (int i = 0; i <= 9; i++){
if (c == i) // This isn't doing what I want it to do
arr1[i] += 1;
}
}
for (int i = 0; i <= 9; i++)
printf ("%c ", arr1[i]);
}
The trouble seems to be the line that i've added to comment above. The line if (c == i) is intended to compare a user inputed digit (as it's entered by the user, not the ASCII value) and compare it with i.
So how can I compare c and i as the same type? I've tried changing the type of getchar() to char, signed int, unsigned int but it doesn't seem to make any difference.
You have to substract '0'.
You are printing char using %c for count.
You are incrementing by the count by i in the loop rather you wanted to increment by 1 for each character.
Corrected code:
int main(void){
int arr1[10] = {0};
int c;
while ((c = getchar()) != '\n'){
for (int i = 0; i <= 9; i++){
if (c - '0' == i)
arr1[i] += 1;
}
}
for (int i = 0; i <= 9; i++)
printf ("%d ", arr1[i]);
}
You have to perform the following operation to convert the ASCII value to corresponding integer,
c=c-48;
Inside your for loop,
arr1[i] += i;
should be,
arr1[i] += 1;
#include <stdio.h>
int main(void){
int arr1[10] = {0};
char table[] = "0123456789";
int c;
while ((c = getchar()) != '\n'){
for (int i = 0; i <= 9; i++){
if (c == table[i])//or table[i] --> "0123456789"[i]
arr1[i] += 1;
}
}
for (int i = 0; i <= 9; i++)
printf ("%d ", arr1[i]);
}
getchar will return ASCII code for c, not the numerical value. Simplest solutions exploits the fact that numbers 0-9 are sequential in the ASCII table, just subtract the offset:
int number = getchar() - '0';
if (number == i) {
//....
}
This is just an example, always check the return value of getchar for error codes.
Finally, in this line:
printf ("%c ", arr1[i]);
Use %d as format specifier instead: you want to print a number, not a character.

Resources