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;
}
Related
Problem:
How can print string num? It seems that final statement cannot execute?
Question desciptions:
Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!
Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.
/* Have Fun with Numbers */
#include <stdio.h>
#include <string.h>
int book[10] = { 0 };
int main(int argc, char* argv[])
{
char num[22];
int temp = 0;
scanf_s("%s", num, 1);
// Length of numbers
int len = strlen(num);
int flag = 0;
for (int i = len - 1; i >= 0; --i) {
// Convert an ASCII value of a digit into an integer
temp = num[i] - '0';
// Add 1 each time read a digit
++book[temp];
temp = temp * 2 + flag;
flag = 0;
if (temp >= 10) {
temp -= 10;
flag = 1;
}
// Convert an integer into an ASCII value of a digit
num[i] = (temp + '0');
// Subtract 1 each time generate a digit
--book[temp];
}
int flag1 = 0;
for (int i = 0; i < 10; ++i) {
if (book[i] != 0) {
flag1 = 1;
}
}
printf("%s", (flag == 1 || flag1 == 1) ? "No\n" : "Yes\n");
if (flag == 1) {
printf("1");
}
printf("%s", num);
return 0;
}
In this like
scanf_s("%s", num, 1);
You are reporting the buffer size as 1 to scanf_s() while the actual size is 22.
Use correct buffer size.
scanf_s("%s", num, 22);
or
scanf_s("%s", num, (unsigned)(sizeof(num) / sizeof(*num)));
As the title says %s is not working properly This is for a code wars so %s needs to be able to work with the array to pass the sample test cases; Cannot change function declaration of playPass. Using Ascii table. Also the for loop to print in main() works and gives me correct output.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// takes a string and shifts letter n value;
// lower cases every other element if it contains a letter
// replaces number with a 9 complement
// returns array with values reversed.
char* playPass(char* s, int n)
{
int length = strlen(s);
char *pass= (char *)malloc(length*sizeof(char)+1);
char a;
int letter, i;
for(i=0; i< length; i++)
{
a = s[i];
letter = a;
if( letter >= 65 && letter <=90 )
{
letter +=n;
if(letter >90)
{
letter -=90;
letter +=64;
}
if((i+1) % 2 == 0 )
{
letter += 32;
}
a = letter;
}
else if(letter >= 48 && letter <= 57)
{
letter -= 48;
letter = 9 - letter;
a = letter + '0';
}
pass[length - i] = a;
}
return pass;
}
// answer should be
int main (){
char* s ={"I LOVE YOU!!!"};
int length = strlen(s);
int k = 1;
s =playPass( s,k );
int i;
printf(" %s", s);
for(i = 0; i <= length; i++)
{
printf(" %c", s[i]);
}
}
%s works only with null terminated char *
char* playPass(char* s, int n) {
…
for() {
…
}
pass[i] = '\0'; //Null terminate here.
return pass;
}
so figured it out.
the end where i assined the new value to the new array
pass[length - i] = a;
made it to where it never wrote a value to the first element so
pass[0]= NULL;
had to change it to
pass[length - (i-1)] = a;
thanks for the help everyone, I also cleaned up the code from the magic numbers Great tip #phuclv!
I am self teaching C programming.
I am trying to count number of int present in given string which are separated by space.
exp:
input str = "1 2 11 84384 0 212"
output should be: 1, 2, 11, 84384, 0, 212
total int = 6
When I try. It gives me all the digits as output which make sense since I am not using a right approach here.
I know in python I can use str.split (" ") function which can do my job very quickly.
But I want to try something similar in C. Trying to create my own split method.
#include <stdio.h>
#include <string.h>
void count_get_ints(const char *data) {
int buf[10000];
int cnt = 0, j=0;
for (int i=0; i<strlen(data); i++) {
if (isspace(data[i] == false)
buf[j] = data[i]-'0';
j++;
}
printf("%d", j);
}
// when I check the buffer it includes all the digits of the numbers.
// i.e for my example.
// buf = {1,2,1,1,8,4,3,8,4,0,2,1,2}
// I want buf to be following
// buf = {1,2,11,84384,0,212}
I know this is not a right approach to solve this problem. One way to keep track of prev and dynamically create a memory using number of non space digits encountered.
But I am not sure if that approach helps.
You want to build your number incrementally until you hit a space, then put that into the array. You can do this by multiplying by 10 then adding the next digit each time.
void count_get_ints(const char *data) {
int buf[10000];
int j = 0;
int current_number = 0;
// Move this outside the loop to eliminate recalculating the length each time
int total_length = strlen(data);
for (int i=0; i <= total_length; i++) {
// Go up to 1 character past the length so you
// capture the last number as well
if (i == total_length || isspace(data[i])) {
// Save the number, and reset it
buf[j++] = current_number;
current_number = 0;
}
else {
current_number *= 10;
current_number += data[i] - '0';
}
}
}
I think strtok will provide a cleaner solution, unless you really want to iterate over every char in the string. It has been a while since I did C, so please excuse any errors in the code below, hopefully it will give you the right idea.
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[19] = "1 2 11 84384 0 212";
const char s[2] = " ";
char *token;
int total;
total = 0;
token = strtok(str, s);
while (token != NULL) {
printf("%s\n", token);
total += atoi(token);
token = strtok(NULL, s);
}
printf("%d\n", total);
return 0;
}
You can check the ascii value of each character by doing c-'0'. If it's between [0,9], then it's an integer. By having a state variable, when you're inside an integer by checking if a given character is a number of space, you can keep track of the count by ignoring white space. Plus you don't need a buffer, what happens if data is larger than 10,000, and you write pass the end of the buffer?, undefined behavior will happen. This solution doesn't require a buffer.
Edit, the solution now prints the integers that are in the string
void count_get_ints(const char *data) {
int count = 0;
int state = 0;
int start = 0;
int end = 0;
for(int i = 0; i<strlen(data); i++){
int ascii = data[i]-'0';
if(ascii >= 0 && ascii <= 9){
if(state == 0){
start = i;
}
state = 1;
}else{
//Detected a whitespace
if(state == 1){
count++;
state = 0;
end = i;
//Print the integer from the start to end spot in data
for(int j = start; j<end; j++){
printf("%c",data[j]);
}
printf(" ");
}
}
}
//Check end
if(state == 1){
count++;
for(int j = start; j<strlen(data); j++){
printf("%c",data[j]);
}
printf(" ");
}
printf("Number of integers %d\n",count);
}
I believe the standard way of doing this would be using sscanf using the %n format specifier to keep track of how much of the string is read.
You can start with a large array to read into -
int array[100];
Then you can keep reading integers from the string till you can't read anymore or you are done reading 100.
int total = 0;
int cont = 0;
int ret = 1;
while(ret == 1 && total < 100) {
ret = sscanf(input, "%d%n", &array[total++], &cont);
input += cont;
}
total--;
printf("Total read = %d\n", total);
and array contains all the numbers read.
Here is the DEMO
Example using strtol
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <ctype.h>
int count_get_ints(int output[], int output_size, const char *input) {
const char *p = input;
int cnt;
for(cnt = 0; cnt < output_size && *p; ++cnt){
char *endp;
long n;
errno = 0;
n = strtol(p, &endp, 10);
if(errno == 0 && (isspace((unsigned char)*endp) || !*endp) && INT_MIN <= n && n <= INT_MAX){
output[cnt] = n;
while(isspace((unsigned char)*endp))
++endp;//skip spaces
p = endp;//next parse point
} else {
fprintf(stderr, "invalid input '%s' in %s\n", p, __func__);
break;
}
}
return cnt;
}
int main(void) {
const char *input = "1 2 11 84384 0 212";
int data[10000];
int n = sizeof(data)/sizeof(*data);//number of elements of data
n = count_get_ints(data, n, input);
for(int i = 0; i < n; ++i){
if(i)
printf(", ");
printf("%d", data[i]);
}
puts("");
}
Assuming you don't have any non-numbers in your string, you can just count the number of spaces + 1 to find the number of integers in the string like so in this pseudo code:
for(i = 0; i < length of string; i++) {
if (string x[i] == " ") {
Add y to the list of strings
string y = "";
counter++;
}
string y += string x[i]
}
numberOfIntegers = counter + 1;
Also, this reads the data between the white spaces. Keep in mind this is pseudo code, so the syntax is different.
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.
For example, the user shall put the input like that, "ABC123," but not "ABC 123" or "A BC123."
Here is my code:
unsigned int convert_to_num(char * string) {
unsigned result = 0;
char ch;
//printf("check this one %s\n", string);
while(ch =*string++) result = result * 26 + ch - 'A' + 1;
return result;
}
int main()
{
char input_string[100];
char arr_col[100] = {'\0'};
char arr_row[100] = {'\0'};
int raiseflag;
int started_w_alpha =0;
int digitflag = 0;
while(scanf("%s", &input_string) != EOF) {
int i = 0, j = 0, digarr = 0;
while (i <=5) {
if (input_string[i] == '\0') {printf("space found!");}
if ((input_string[i] >= 'A' && input_string[i] <= 'Z') && (digitflag == 0)) {
started_w_alpha = 1;
arr_col[j] = input_string[i]; j++;
}
//printf("something wrong here %s and %d and j %d\n", arr_holder, i, j);
if (started_w_alpha == 1) {
if (input_string[i] >=48 && input_string[i]<=57){ digitflag = 1; arr_row[digarr] =input_string[i]; digarr++; }
}
i++; if (i == 5) { raiseflag =1; }
}
printf(" => [%d,%s]\n", convert_to_num(arr_col), arr_row);
if (raiseflag == 1) { raiseflag = 0; memset(arr_col, 0, 5); memset(input_string, 0, 5); memset(arr_row, 0, 5); digitflag = 0; started_w_alpha = 0; }
}
return 0;
}
Apparently, \0 doesn't work in my case because I have an array of 5 and user can put 2 chars. I want to exit the loop whenever a space is found in between the characters.
This is the whole code. I added {'\0'} my array because of the extra characters I get when there is less than 5 characters.
Thanks!
Since the index is starting from 0 and input_string[5]; array size is 5, the only valid indexes are from 0 to 4.
but your loop while (i <=5) { go till 5, it is mean you exceed the array.
If you insert 5 characters to the string, the terminating null is the 6th.
Since you exceed the array it written over some other variable. but you still can find it when you check input_string[5]
So if you want to insert 5 characters you array size should be at least 6
char input_string[6];
if you want to check only the first 5 elements you'll have to change the loop to:
while (i < 5) {
and as I wrote in the comment if you find the terminating null, no use to continue the loop, since it contain garbage or leftover from the previous iteration.
Therefor you should break if it found, like this:
if (input_string[i] == '\0') {printf("space found!"); break;}
EDIT
check this program: it use fgets to read the whole input, then search for white spaces.
Note it doesn't trim the input, means it won't remove spaces when thay appear at the beginning or at the end of the input.
#include <ctype.h>
#include <string.h>
#include <stdio.h>
int main()
{
int i ,size;
char input_string[100];
fgets(input_string,100,stdin);
i=0;
size = strlen(input_string);
while (i<size-1){ //enter is also count
if (isspace(input_string[i]))
{
printf("space found!");
break;
}
i++;
}
return 0;
}
EDIT2
Now with a trim, so it will remove leading and ending spaces:
#include <ctype.h>
#include <string.h>
#include <stdio.h>
char* trim(char *input_string)
{
int i=0;
char *retVal = input_string;
i = strlen(input_string)-1;
while( i>=0 && isspace(input_string[i]) ){
input_string[i] = 0;
i--;
}
i=0;
while(*retVal && isspace(retVal[0]) ){
retVal ++;
}
return retVal;
}
int main()
{
int i ,size;
char input_string[100],*ptr;
fgets(input_string,100,stdin);
ptr = trim(input_string);
i=0;
size = strlen(ptr);
while (i<size){
if (isspace(ptr[i]))
{
printf("space found!");
break;
}
i++;
}
return 0;
}