I have problem with extracting numbers from string.
Problem is I can not use strtol or isdigit functions as teacher requested so.
I am supposed to save numbers in new array.
For example, string input:
11-some12meh13text-14
.
So new array would be:
11,12,13,14
(NOT -14)
I came to idea to do following:
char str1[150];
int array[20];
int temporary, i=0, j=0; //i - for string, j - for array
for(i=0;i<=strlen(str1);i++) {
if(i==0) { //not needed to check if char before was number
if((str1[i]>=0) && (str1[i]<=9))temporary=str1[i];
if((str1[i+1]<=0) && (str1[i+1]>=9)) {//if next char is NOT number
array[j]=temporary;
j++;
}
}
else if(i!=0) { //needs to be checked if char before was number
if((str1[i]>=0) && (str1[i]<=9)) {
if((str1[i-1]>=0) && (str1[i-1]<=9))temporary=temporary*10+str1[i];
else temporary=str1[i];
if((str1[i+1]<=0) && (str1[i+1]>=9)) {//if next char is NOT number
array[j]=temporary;
j++;
}
}
}
}
I tried it on my PC, but program crashes and I have no idea or ability to find what I did wrong.
Please help!
Thank you!
The integral values of characters '0'...'9' are not 0...9.
Hence, change every occurrence of str1[k] to str1[k]-'0'.
If using sscanf() is allowed, this will parse the string for integers. The %n specifier will report the number of characters processed by the scan. This lets you move through the string.
When the scan for an integer fails ( != 1), the scanset "%*[^0-9\n]%n" scans and discards characters that are not a digit or newline. The %n captures the number of characters processed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( ) {
char str1[150] = {"0+1-=2!3*4-5/6#7&8|9^10"};
int array[20] = {0};
int offset = 0;
int each = 0;
int loop = 0;
int used = 0;
int length = 0;
length = strlen ( str1);
do {
sscanf ( str1 + offset, "%*[^0-9\n]%n", &used);
offset += used;
if ( ( sscanf ( str1 + offset, "%d%n", &array[each], &used)) == 1) {
offset += used;
each++;
if ( each >= 20) {
break;
}
}
} while ( offset < length);
for ( loop = 0; loop < each; loop++) {
printf ( "%d\n", array[loop]);
}
return 0;
}
Here is a version of your code that seems to work
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( ) {
char str1[150] = {"-0+1-=2!3*4-text-5/6#7&8|9^10 11end"};
int array[20] = {0};
int each = 0;
int loop = 0;
int saved = 1;
int length = 0;
int temporary = 0, i=0;
length = strlen ( str1);
for ( i = 0; i < length; i++) {
if ( ( str1[i] >= '0') && ( str1[i] <= '9')) {//found a digit
temporary = ( temporary * 10) + ( str1[i] - '0');
saved = 0;//flag not saved. temporary value may change
}
else {//found NOT a digit
if ( i > 0 && !saved) {//not at first character and not saved
array[each] = temporary;//save integer
each++;
saved = 1;//flag saved
temporary = 0;//reset
if ( each >= 20) {
break;
}
}
}
}
if ( !saved && each < 19) {//end of string is an integer. save it
array[each] = temporary;
each++;
}
for ( loop = 0; loop < each; loop++) {
printf ( "%d\n", array[loop]);
}
return 0;
}
Related
I am super new to programming and I am having a problem with one of the questions where i am supposed to write a C program to let the user enter some numbers and sort the entered elements and find the median of it. And it should stop getting inputs once the user presses enter.
this is my code and idk where it went wrong(btw sorry for asking such a simple question)
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
int i = 0;
int j,k,m,num;
int arr[20];
while(i<20 )
{
printf("Enter a number: ");
scanf("%d",&num);
if(num == '\n') break;
arr[i] = num;
i++;
}
n = sizeof(arr)/sizeof(arr[0]);
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(arr[i] < arr[j])
{
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
if(n%2 != 0)
{
printf("The median is %d", arr[n/2] ) ;
}
else printf("The median is %.2f", arr[(n-1)/2] + arr[n/2]/2.0);
return 0;
}
If you want to stop on empty line, you cannot use scanf. The reason is that scanf("%d", ...) skips all whitespace characters from user input while waiting for the use to enter a number. Here "whitespace" includes the new-line character '\n'. So the user cannot make scanf return by pressing Enter - only an end-of-file (Ctrl+D on linux) or bogus input (non-number) will make scanf return.
So you have to replace scanf by the combination fgets+sscanf. Consider the following code:
while (i < 20)
{
int num;
char str[15];
printf("Enter a number: ");
if (!fgets(str, sizeof str, stdin))
break;
if (sscanf(str, "%d", &num) != 1)
break;
arr[i] = num;
i++;
}
It uses fgets to input a line of input, and sscanf to parse that line. If there is nothing in the line, sscanf will fail (it returns 1 for success; any other value for failure).
Notes:
If input is too long, it will be split into two lines, which will be surprising for the user
If the user inputs more than one number on the line, extra numbers will be silently ignored
The condition of fgets's return value terminates user input also on end-of-file; this is good if you supply input to your program by redirecting it from a file
Input could be processed character by character until either twenty integers are stored or a newline is found.
As digits are read, accumulate them into a value, checking for overflow.
Upon reading whitespace or another character, store the values in the array.
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
int main ( void) {
int ch = 0;
int value = 0;
int sign = 1;
int digits = 0;
int arr[20] = { 0};
int n = 0;
int i = 0;
int j = 0;
int k = 0;
while ( n < 20) {
while ( EOF != ( ch = fgetc ( stdin))) {//read a character
if ( isdigit ( ( unsigned char)ch)) {
ch -= '0';//character to int as '1' to 1
digits = 1;
if ( 1 == sign) {
if ( value < ( INT_MAX / 10) - ch) {
value *= 10;
value += ch;
}
else {
printf ( "overflow! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
}
if ( -1 == sign) {
if ( value > ( INT_MIN / 10) + ch) {
value *= 10;
value -= ch;
}
else {
printf ( "overflow! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
}
}
else if ( '-' == ch || '+' == ch) {
if ( digits) {
printf ( "invalid sign! reset to + and zero\n");
value = 0;
sign = 1;
digits = 0;
}
else {
sign = ( '-' == ch) ? -1 : 1;
}
}
else if ( digits) {
arr[n] = value;
value = 0;//reset to zero
sign = 1;//reset to +
++n;
digits = 0;
}
if ( '\n' == ch) {
break;
}
}
if ( '\n' == ch || EOF == ch) {
break;
}
}
for ( i = 0; i < n; i++) {
for ( j = i + 1; j < n; j++) {
if ( arr[i] < arr[j]) {
k = arr[i];
arr[i] = arr[j];
arr[j] = k;
}
}
}
for ( i = 0; i < n; i++) {
printf ( "arr[%d] = %d\n", i, arr[i]);
}
if ( n % 2 != 0) {
printf ( "The median is %d\n", arr[n/2]);
}
else {
printf ( "The median is %.2f\n", ( arr[( n - 1) / 2] + arr[n / 2] ) /2.0);
}
return 0;
}
Input and output:
9 1 82 0 3
arr[0] = 82
arr[1] = 9
arr[2] = 3
arr[3] = 1
arr[4] = 0
The median is 3
I'm trying to split a string into chunks of 6 using C and I'm having a rough time of it. If you input a 12 character long string it just prints two unusual characters.
#include <stdio.h>
#include <string.h>
void stringSplit(char string[50])
{
int counter = 0;
char chunk[7];
for (unsigned int i = 0; i < strlen(string); i++)
{
if (string[i] == ' ')
{
continue;
}
int lastElement = strlen(chunk) - 1;
chunk[lastElement] = string[i];
counter++;
if (counter == 6)
{
printf(chunk);
memset(chunk, '\0', sizeof chunk);
counter = 0;
}
}
if (chunk != NULL)
{
printf(chunk);
}
}
int main()
{
char string[50];
printf("Input string. \n");
fgets(string, 50, stdin);
stringSplit(string);
return(0);
}
I appreciate any help.
Your problem is at
int lastElement = strlen(chunk) - 1;
Firstly, strlen counts the number of characters up to the NUL character. Your array is initially uninitialized, so this might cause problems.
Assuming your array is filled with NULs, and you have, let's say, 2 characters at the beginning and you are looking to place the third one. Remember that your 2 characters are at positions 0 and 1, respectively. So, strlen will return 2 (your string has 2 characters), you subtract one, so the lastElement variable has the value 1 now. And you place the third character at index 1, thus overwriting the second character you already had.
Also, this is extremely inefficient, since you compute the number of characters each time. But wait, you already know how many characters you have (you count them in counter, don't you?). So why not use counter to compute the index where the new character should be placed? (be careful not to do the same mistake and overwrite something else).
The function is wrong.
This statement
int lastElement = strlen(chunk) - 1;
can result in undefined behavior of the function because firstly the array chunk is not initially initialized
char chunk[7];
and secondly after this statement
memset(chunk, '\0', sizeof chunk);
the value of the variable lastElement will be equal to -1.
This if statement
if (chunk != NULL)
{
printf(chunk);
}
does not make sense because the address of the first character of the array chunk is always unequal to NULL.
It seems that what you mean is the following.
#include <stdio.h>
#include <ctype.h>
void stringSplit( const char s[] )
{
const size_t N = 6;
char chunk[N + 1];
size_t i = 0;
for ( ; *s; ++s )
{
if ( !isspace( ( unsigned char )*s ) )
{
chunk[i++] = *s;
if ( i == N )
{
chunk[i] = '\0';
i = 0;
puts( chunk );
}
}
}
if ( i != 0 )
{
chunk[i] = '\0';
puts( chunk );
}
}
int main(void)
{
char s[] = " You and I are beginners in C ";
stringSplit( s );
}
The program output is
Youand
Iarebe
ginner
sinC
You can modify the function such a way that the length of the chunk was specified as a function parameter.
For example
#include <stdio.h>
#include <ctype.h>
void stringSplit( const char s[], size_t n )
{
if ( n )
{
char chunk[n + 1];
size_t i = 0;
for ( ; *s; ++s )
{
if ( !isspace( ( unsigned char )*s ) )
{
chunk[i++] = *s;
if ( i == n )
{
chunk[i] = '\0';
i = 0;
puts( chunk );
}
}
}
if ( i != 0 )
{
chunk[i] = '\0';
puts( chunk );
}
}
}
int main(void)
{
char s[] = " You and I are beginners in C ";
for ( size_t i = 3; i < 10; i++ )
{
stringSplit( s, i );
puts( "" );
}
}
The program output will be
You
and
Iar
ebe
gin
ner
sin
C
Youa
ndIa
rebe
ginn
ersi
nC
Youan
dIare
begin
nersi
nC
Youand
Iarebe
ginner
sinC
YouandI
arebegi
nnersin
C
YouandIa
rebeginn
ersinC
YouandIar
ebeginner
sinC
I need to write a C program that counts the number of characters and digits in a file. I believe my best attempt is close, but the program must call a given function, mostfrequent(), and I cannot figure out how to implement it into my main so that they work together. Any help would be greatly appreciated. Thank you.
// this is the function my program is required to use.
int mostfrequent(int *a, int length) {
int index = 0;
int max = a[0];
int i;
for (i = 1; i < length; i++) {
if (a[i] > max) {
max = a[i];
index = i;
}
}
return index;
}
// this is my closest attempt at a working program so far, but it does
// not call mostfrequent() which I need it to do.
int main() {
typedef FILE *ptr_file;
int x, i, j;
int length;
char c;
char ch[1000];
int a = 65;
c = getc(ptr_file);
ptr_file = fopen("file.txt", "r");
if (!ptr_file)
return 1;
while (c != EOF) {
scanf(ptr_file, "%s", ch[i]);
i++;
fclose(ptr_file);
}
for (i = 0; i < length; i++) {
for (j = 0; j < length; j++) {
if (a < 116) {
if (char(a) == 'ch[j]')
char max_char_temp=(char)a
count_temp++;
}
if (count_temp > count) {
count = count_temp;
max_char = max_char_temp;
}
return 0;
}
regarding the question: when to call the most_frequent() function.
After you have created an array (which would be 36 entries long of integers), initialize that array to all zeros, then incremented the appropriate entry for each character read from the input file. (note 36 entries allows for a...z + 0...9 so all other characters read from the file should be discarded.
Then pass the array and 36 to the most_frequent() function
then code similar to the following could do the job:
#include <stdio.h>
#include <stdlib.h>
#include <ctypes.h> // isalpha(), isdigit(), toupper()
#define NUM_ALPHA (26)
int main( void )
{
int array[36] = {'\0'};
//...open file, etc
//then assure all processed characters are upper case or numeric
// and update the count in the array
int ch;
while( ch = getc( file ) != EOF && '\n' != ch)
{
if ( isalpha(ch) )
{
ch = toupper(ch);
array[ch - 'A']++;
}
else if (isdigit(ch) )
{
array[ (ch-'0') + NUM_ALPHA ]++;
}
}
int index = mostfrequent( array, sizeof(array)/sizeof(array[0]);
//... do what is needed with 'index' for instance
printf( "the highest occurring char is:" );
if( index < NUM_ALPHA )
{
printf( "%c\n", index+'A' );
}
else
{
printf( "%d\n", (index-NUM_ALPHA)+'0');
}
fclose( file );
return 0;
}
however, note that mostfrequent() only returns the index to the first entry encountered with the max value, when there are multiple entries with the same max value.
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;
}
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;
}