How to parse out integers from a line with characters and integers - c++

For a C/C++ assignment, I need to take an input line, starting with the character 's', followed by UP TO 3 separate integers. My issue is that, without vectors, I don't know how to account for an unknown number of integers (1-20).
For example, a test input would look like:
s 1 12 20
It was suggested to me to use cin.getline and take the whole line as a string, but how would I know where each integer would lie in a character array because of the possibility of single or double digits, let alone the number of integers in said string?

Construct a std::istringstream from the contents of the line, then keep using operator>> into an int, until it fail()s, stuffing each integer into a std::vector (after using the operator>> initially, once, to take care of the leading character).

You can mimic vectors using dynamic memory allocation. Initially create an array of size 2, using int *a = new int[2];
When this array fills up, make a new array of double the size, copy the old array in the new one and reassign a to the new array. Keep doing this until you have met the requirement.
EDIT
So getting the numbers through the string stream, if the array fills up, you could do:
int changeArr(int *a, int size){
int *b = new int[size*2];
for(int i=0;i<size;i++){
b[i] = a[i];
}
a = b;
return size*2;
}
int getNos(istringstream ss){
int *a = new int[2];
int cap = 2, i=0, number;
while(ss){
if(i>=cap){
cap = changeArr(a, cap);
}
ss >> a[i];
i++;
}
}
I have skipped the part about the first character, but I guess you can handle that.

Without vectors, you have a couple of approaches. (1) read an entire line at a time and tokenize the line with strtok or strsep, or (2) use the standard features built into strtol to walk down the string separating values with the pointer and end-pointer parameters to the function.
Since you know the format, you can easily use either. Both 1 & 2 above do the same thing, you are just using the tools in strtol to both tokenize and convert to a number in a single step. Here is a short example for handling a string followed by an unknown number of digits on each line:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
enum { BASE = 10, MAXC = 512 };
long xstrtol (char *p, char **ep, int base);
int main (void) {
char buf[MAXC] = "";
while (fgets (buf, MAXC, stdin)) { /* for each line of input */
char *p, *ep; /* declare pointers */
p = buf; /* reset values */
errno = 0;
printf ("\n%s\n", p); /* print the original full buffer */
/* locate 1st digit in string */
for (; *p && (*p < '0' || '9' < *p); p++) {}
if (!*p) { /* validate digit found */
fprintf (stderr, "warning: no digits in '%s'\n", buf);
continue;
}
/* separate integer values */
while (errno == 0)
{ int idx = 0;
long val;
/* parse/convert each number in line into long value */
val = xstrtol (p, &ep, BASE);
if (val < INT_MIN || INT_MAX < val) { /* validate int value */
fprintf (stderr, "warning: value exceeds range of integer.\n");
continue;
}
printf (" int[%2d]: %d\n", idx++, (int) val); /* output int */
/* skip delimiters/move pointer to next digit */
while (*ep && *ep != '-' && (*ep < '0' || *ep > '9')) ep++;
if (*ep)
p = ep;
else
break;
}
}
return 0;
}
/** a simple strtol implementation with error checking.
* any failed conversion will cause program exit. Adjust
* response to failed conversion as required.
*/
long xstrtol (char *p, char **ep, int base)
{
errno = 0;
long val = strtol (p, ep, base);
/* Check for various possible errors */
if ((errno == ERANGE && (val == LONG_MIN || val == LONG_MAX)) ||
(errno != 0 && val == 0)) {
perror ("strtol");
exit (EXIT_FAILURE);
}
if (*ep == p) {
fprintf (stderr, "No digits were found\n");
exit (EXIT_FAILURE);
}
return val;
}
(the xstrtol function just moves the normal error checking to a function to unclutter the main body of the code)
Example Input
$ cat dat/varyint.txt
some string 1, 2, 3
another 4 5
one more string 6 7 8 9
finally 10
Example Use/Output
$ ./bin/strtolex <dat/varyint.txt
some string 1, 2, 3
int[ 0]: 1
int[ 1]: 2
int[ 2]: 3
another 4 5
int[ 0]: 4
int[ 1]: 5
one more string 6 7 8 9
int[ 0]: 6
int[ 1]: 7
int[ 2]: 8
int[ 3]: 9
finally 10
int[ 0]: 10
You can provide a bit of tidying up, but this method can be used to parse an unknown number of values reliably. Look it over and let me know if you have any questions.

Since vectors aren't allowed, you'll need to find out how many numbers are in the line before you can make an array to hold them.
I won't just give you the entire code, since this is homework, but I'll show you what I would do to solve your problem.
If your lines will always look like this: "s number" or "s number number" or "s number number number", then you can easily find the number of numbers in the line by counting the spaces!
There will be one space in any string with one number (between the s and that number), and one more space for each number that follows the first.
So let's count the spaces!
int countSpaces(string s) {
int count = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
count++;
}
}
return count;
}
Passing these strings:
string test1 = "s 123 4 99999";
string test2 = "s 1";
string test3 = "s 555 1337";
to the countSpaces function will give us:
3
1
2
And with that information, we can make an array with the correct size to hold each value!
EDIT
Now I realize that you're having trouble grabbing the numbers from the string.
What I would do, is use the above method to find the number of numbers in the line. Then, I would use the std::string.find() function to determine where, and if, any spaces are in the string.
So let's say we had the line: s 123 45 678
countSpaces would tell us we have 3 numbers.
Then we make an array to hold our three numbers. I would also cut off the s part so you don't have to worry about it anymore. Note that you can use std::stoi to turn a string into a number!
Now we can loop while find(' ') doesn't return -1.
In our loop, I would take the substring from 0 to the first space, like so:
num = std::stoi( myLine.substr(0, myLine.find(' ') )
Then you can cut off the part you just used:
myLine = myLine.substr( myLine.find(' ') );
This will grab a number off the front of your string, then chop off that number from the string, and repeat the process while there is still a space in the string.
EDIT:
If you aren't guaranteed to have one space between each number, then you can delete excess spaces before doing this method or you can do it during the countSpaces loop. At that point, it would make more sense to call the function countNums or such.
An example function to remove stretches of spaces and replace them with one space:
void removeExtraSpaces(string s) {
bool inSpaces = (s[0] == ' ');
for (int i = 1; i < s.size(); i++) {
if (s[i] == ' ') {
if(inSpaces) {
s.erase(i);
} else {
inSpaces = true;
}
} else if(inSpaces) {
inSpaces = false;
}
}
}

Related

Remove duplicates from input without use of any data structures

Disclaimer: This question is more of a challenge, and the post is also quite long. Read only in free time!
The Problem:
Basically, suppose there is a single line of integer inputs:
32352\n // assuming single digits only and no spaces for simplification
We have to remove duplicates from the inputs, and then display them. So, output should be:
After removing duplicates: 2, 3, 5 // display them in any order
However, there is a catch:
Do not use any data structures containers.
Edit: I believe containers are what I meant (thanks Vlad!).
So, my question is: What is the error in my implementation, and is there another (better) way to do it?
My thought process:
Since we are not allowed use of any data structure, we cannot store the inputs (I think?).
However, since it is already stored in memory on input, that is not a problem.
More of a problem is removing the duplicates. We will have to manipulate the input stream.
The first thing that struck me is that we can sort the inputs. That is,
32352
becomes:
22335
And now, simply print the first element of each range.
Working on this idea, I came across the std::cin.get() and std::cin.putback() methods, both accepting a char.
I also realized I would have to use recursion.
And hence, the code becomes (I have used insertion sort):
The Code:
The sort() function is where the error is. It uses a running index ala arrays, and this is used to uniquely identify each element.
In each iteration, the index_of_element element is found and selected, and we determine where in the remaining (virtual) array, we need to place it. For example, if in our original input:
32352 // S = sorted subarray
SU--U // U = unsorted subarray
, the first 2 is selected, we "shift" 3 (as 3 < 2).
Now, there are no more elements left to shift, we "place" 2.
The result should become:
23352
SSU-U
The (buggy) implementation:
bool sort(int index_of_element, int index = 0, char prev_element = 0)
{
static char element;
char digit;
// retrieve an element from memory
std::cin.get(digit);
// If not end of input
if(digit != '\n')
{
// store the element for comparision
if(index == index_of_element)
{
element = digit;
}
// continue forward until '\n'
bool result = sort(index_of_element, index + 1, digit);
// if we are in sorted subarray
if(index <= index_of_element)
{
// If element belongs here(also if this is first element(prev_element is 0)), place it
if(element > prev_element)
{
digit = element;
// Signal that element has been placed
element = 0;
}
// Else, if element not already placed, we need to shift elements
else if(element != 0)
{
// Place the previous element here
digit = prev_element;
}
}
// Put it back in memory
std::cin.putback(digit);
// And return the result
return result;
}
// Which is generated here when end of input is reached
else
{
// If sorted all elements, break loop
if(index_of_element == index)
{
return false;
}
// Else, continue sorting
else
{
return true;
}
}
}
(A wall of code, but I didn't want to skip anything relevant), and it should be used as:
...
int index_of_element = 0;
while(sort(index_of_element++));
...
The display function is ready, and it works properly.
What I do know is that it gets stuck in an infinite loop and the values are lost.
What is going wrong?
And should I add the output (The post is already very long)?
The problem seems to be that you don't put the newline back into the stream, while your code assumes that it will be there.
That is, after your first pass, digit != '\n' is always true.
Put the newline back into the stream, or break when you've reached the true end-of-stream.
(There could also be problems with (ab)using std::cin like this, but I'm not sure, and that's another matter anyway.)
You can do it with only function objects, in a single pass.
#include <iostream>
#include <sstream>
#include <functional>
void print_unique_ints(std::istream & in, std::ostream & out, std::function<bool(int)> unseen) {
for (int i; in >> i;) {
if (unseen(i)) {
out << i << ' ';
print_unique_ints(in, out, [&](int j){ return (i != j) && unseen(j); });
return; // not actually needed, previous call only ends when input is exhausted
}
}
}
int main() {
print_unique_ints(std::cin, std::cout, [](int){ return true; });
}
See it live
Each call to print_unique_ints skips previously seen ints, prints the unseen int, and adds to the filter
Substituting values for variables; and function calls for expressions; in the first call
for (int i; in >> i;) { // i = 3
if (true) {
out << 3 << ' ';
print_unique_ints(...) // see below
}
}
The second
for (int i; in >> i;) { // i = 2
if ((3 != i) && true) {
out << 2 << ' ';
print_unique_ints(...) // see below
}
}
The third
for (int i; in >> i;) { // i = 3, 5
if ((2 != i) && (3 != i) && true) { // skips over the 3
out << 5 << ' ';
print_unique_ints(...) // see below
}
}
The forth
for (int i; in >> i;) { // i = 2
if ((5 != i) && (2 != i) && (3 != i) && true) { // skips the 2 and finds the end of input
}
}
Note that && true never changes the result in the if
A variation of bitset (or mask) implem...using the commutative property of multiplication
Take a function f which maps every digit to a unique prime p_i
0 1 2 3 4 5 6 7 8 9
2,3,5,7,9,11,13,17,19,23
If all numbers are found the total amount to N=2*3*5*7*9*11*13*17*19*23=2007835830
Consume cin as c, if f(c) divides N, print c and update N /= f(c)
#include <iostream>
#include <sstream>
int f(char c){
if(c=='0') return 2;
if(c=='1') return 3;
if(c=='2') return 5;
if(c=='3') return 7;
if(c=='4') return 9;
if(c=='5') return 11;
if(c=='6') return 13;
if(c=='7') return 17;
if(c=='8') return 19;
if(c=='9') return 23;
}
int main() {
std::istringstream in("2 2 2 3 5");
int N = 2007835830;
char c;
while(in >> c){
if(c=='\n') break;
int p_i = f(c);
if(N % p_i == 0){
N = N/p_i;
std::cout<<c<<" ";
}
}
}
I am sure that this phrase
Remove duplicates from input without use of any data structures
means that you shall not use any container like for example std::string or an ordinary array.
The assignment is not simple for a beginner.
Here are my five cents.
#include <iostream>
#include <type_traits>
template <typename T>
T remove_duplicates( T n )
{
static_assert ( std::is_integral<T>::value );
const T Base = 10;
T result = n % Base;
for ( T multiplier = 1; n /= Base; )
{
T digit = n % Base;
T tmp = result;
bool unique = true;
while ( ( unique = tmp % Base != digit ) && ( tmp /= Base ) );
if ( unique )
{
multiplier *= Base;
result = digit == 0 ? result * multiplier + digit
: digit * multiplier + result;
}
}
return result;
}
int main()
{
for ( int n : { 0, 1, 10, 101, 100, 10203, -1, -10, -101, -100, - 10203 } )
{
std::cout << n << ": " << remove_duplicates( n ) << '\n';
}
return 0;
}
The program output is
0: 0
1: 1
10: 10
101: 10
100: 10
10203: 1230
-1: -1
-10: -10
-101: -10
-100: -10
-10203: -1230
That is you are building a new number from the source number by checking whether the new number already contains a digit from the source number.
The function can work with any integer type signed or unsigned. It correctly processes digits equal to 0.
It was said not to use any arrays, vectors, stacks, queues etc and neither our own implementations of it. I simplified the condition.
Well I've got bad news for you; this is not possible.
Given an input of length N you will need to somehow remember the previous N - 1 values to decide whether to print the Nth value or not. This is not possible with constant space.
So you need some data structure.
Now ...
Since we are not allowed use of any data structure, we cannot store the inputs (I think?).
However, since it is already stored in memory on input, that is not a problem.
So let's assume the existence of a (mutable) array of length N, containing the input values. Now we can solve this without using additional storage / data structures:
Select some value as special value
Iterate over the numbers until you find a value which is not that special value. print that value. Write the special value to the array where you found the value you just printed. finish iterating over the numbers, overwritte each occurrence of the just printed value with the special value.
repeat (from 2) until the input consists only of special values.
You just need to think about a way to handle the case where the special value was present in the input from the start.

C++ How to output the letters or numbers from input of letters or numbers

So let's say we have the following case: for ”12323465723” possible answers would be ”abcbcdfegbc” (1 2 3 2 3 4 6 5 7 2 3), ”awwdfegw” (1 23 23 4 6 5 7 23), ”lcwdefgw” (12 3 23 4 6 5 7 23), in this case, the user will input numbers from 1 to 26, not divided by any space and the program itself will suggest 3 ways of interpreting the numbers, getting the most of the combinations from 1 to 26 these being the values from a to z
As you can see this is edited, as this is the last part of the problem, Thank you all who have helped me this far, I've managed to solve half of my problem, only the above mentioned one is left.
SOLVED -> Thank you
This involves a decision between 0 to 2 outcomes at each step. The base cases are there are no more characters or none of them can be used. In the latter case, we backtrack to output the entire tree. We store the word in memory like dynamic programming. This naturally leads to a recursive algorithm.
#include <stdlib.h> /* EXIT */
#include <stdio.h> /* (f)printf */
#include <errno.h> /* errno */
#include <string.h> /* strlen */
static char word[2000];
static size_t count;
static void recurse(const char *const str) {
/* Base case when it hits the end of the string. */
if(*str == '\0') { printf("%.*s\n", (int)count, word); return; }
/* Bad input. */
if(*str < '0' || *str > '9') { errno = ERANGE; return; }
/* Zero is not a valid start; backtrack without output. */
if(*str == '0') return;
/* Recurse with one digit. */
word[count++] = *str - '0' + 'a' - 1;
recurse(str + 1);
count--;
/* Maybe recurse with two digits. */
if((*str != '1' && *str != '2')
|| (*str == '1' && (str[1] < '0' || str[1] > '9'))
|| (*str == '2' && (str[1] < '0' || str[1] > '6'))) return;
word[count++] = (str[0] - '0') * 10 + str[1] - '0' + 'a' - 1;
recurse(str + 2);
count--;
}
int main(int argc, char **argv) {
if(argc != 2)
return fprintf(stderr, "Usage: a.out <number>\n"), EXIT_FAILURE;
if(strlen(argv[1]) > sizeof word)
return fprintf(stderr, "Too long.\n"), EXIT_FAILURE;
recurse(argv[1]);
return errno ? (perror("numbers"), EXIT_FAILURE) : EXIT_SUCCESS;
}
When run on your original input, ./a.out 12323465723, it gives,
abcbcdfegbc
abcbcdfegw
abcwdfegbc
abcwdfegw
awbcdfegbc
awbcdfegw
awwdfegbc
awwdfegw
lcbcdfegbc
lcbcdfegw
lcwdfegbc
lcwdfegw
(I think you have made a transposition in lcwdefgw.)
According to ASCII table we know that from 65 to 90 it A to Z.
so below is the simple logic to achieve what you're trying.
int main(){
int n;
cin>>n;
n=n+64;
char a=(char) n;
if (a>=64 && a<=90)
cout<<a;
else cout<<"Error";
return 0;
}
If you want to count the occurencs of "ab" then this will do it:
int main()
{
char line[150];
int grup = 0;
cout << "Enter a line of string: ";
cin.getline(line, 150);
for (int i = 0; line[i] != '\0'; ++i)
{
if (line[i] == 'a' && line[i+1] == 'b')
{
++grup;
}
}
cout << "Occurences of ab: " << grup << endl;
return 0;
}
If you want to convert an int to an ASCII-value you can do that using this code:
// Output ASCII-values
int nr;
do {
cout << "\nEnter a number: ";
cin >> nr;
nr += 96; // + 96 because the ASCII-values of lower case letters start after 96
cout << (char) nr;
} while (nr > 96 && nr < 123);
Here I use the C style of casting values to keep things simple.
Also bear in mind ASCII-values: ASCII Table
Hope this helps.
This could be an interesting problem and you probably tagged it wrong, There's nothing specific to C++ here, but more on algorithm.
First of all the "decode" method that you described from numerical to alphabetical strings is ambiguious. Eg., 135 could be interpreted as either "ace" or "me". Is this simply an oversight or the intended question?
Suppose the ambiguity is just an oversight, and the user will enter numbers properly separated by say a white space (eg., either "1 3 5" or "13 5"). Let nstr be the numerical string, astr be the alphabetical string to count, then you would
Set i=0, cnt=0.
Read the next integer k from nstr (like in this answer).
Decode k into character ch
If ch == astr[i], increment i
If i == astr.length(), set i=0 and increment cnt
Repeat from 2 until reaching the end of nstr.
On the other hand, suppose the ambiguous decode is intended (the numerical string is supposed to have multiple ways to be decoded), further clarification is needed in order to write a solution. For example, how many k's are there in "1111"? Is it 1 or 2, given "1111" can be decoded either as aka or kk, or maybe even 3, if the counting of k doesn't care about how the entire "1111" is decoded?

Parsing string to get comma-separated integer character pairs

I'm working on a project where I'm given a file that begins with a header in this format: a1,b3,t11, 2,,5,\3,*4,344,00,. It is always going be a sequence of a single ASCII character followed by an integer separated by a comma with the sequence always ending with 00,.
Basically what I have to do is go through this and put each character/integer pair into a data type I have that takes both of these as parameters and make a vector of these. For example, the header I gave above would be a vector with ('a',1), ('b',3),('t',11),(',',5)(' ',2),('\',3),('*',4),('3',44) as elements.
I'm just having trouble parsing it. So far I've:
Extracted the header from my text file from the first character up until before the ',00,' where the header ends. I can get the header string in string format or as a vector of characters (whichever is easier to parse)
Tried using sscanf to parse the next character and the next int then adding those into my vector before using substrings to remove the part of the string I've already analyzed (this was messy and did not get me the right result)
Tried going through the string as a vector and checking each element to see if it is an integer, a character, or a comma and acting accordingly but this doesn't work for multiple-digit integers or when the character itself is an int
I know I can fairly easily split my string based on the commas but I'm not sure how to do this and still split the integers from the characters while retaining both and accounting for integers that I need to treat as characters.
Any advice or useful standard library or string functions would be greatly appreciated.
One possibility, of many, would be to store the data in a structure. This uses an array of structures but the structure could be allocated as needed with malloc and realloc.
Parsing the string can be accomplished using pointers and strtol which will parse the integer and give a pointer to the character following the integer. That pointer can be advanced to use in the next iteration to get the ASCII character and integer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 100
struct pair {
char ascii;
int integer;
};
int main( void) {
char input[] = "a1,b3,!0,t11, 2,,5,\\3,*4,34400,";
char *pt = input;//start with pt pointing to first character of input
char *end = input;
int each = 0;
int loop = 0;
int length = 0;
struct pair pairs[SIZE] = { { '\0', 0}};
//assuming input will always end in 00, ( or ,00,)
//remove those three ( or 4 ??) characters
length = strlen ( input);
if ( length > 3) {
input[length - 3] = '\0';
}
for ( each = 0; each < SIZE; each++) {
//get the ASCII character and advance one character
pairs[each].ascii = *pt;
pt++;
//get the integer
pairs[each].integer = strtol ( pt, &end, 10);
//end==pt indicates the expected integer is missing
if ( end == pt) {
printf ( "expected an integer\n");
break;
}
//at the end of the string?
if ( *end == '\0') {
//if there are elements remaining, add one to each as one more was used
if ( each < SIZE - 1) {
each++;
}
break;
}
//the character following the integer should be a comma
if ( *end != ',') {
//if there are elements remaining, add one to each as one more was used
if ( each < SIZE - 1) {
each++;
}
printf ( "format problem\n");
break;
}
//for the next iteration, advance pt by one character past end
pt = end + 1;
}
//loop through and print the used structures
for ( loop = 0; loop < each; loop++) {
printf ( "ascii[%d] = %c ", loop, pairs[loop].ascii);
printf ( "integer[%d] = %d\n", loop, pairs[loop].integer);
}
return 0;
}
Another option is to use dynamic allocation.
This also uses sscanf to parse the input. The %n will capture the number of characters processed by the scan. The offset and add variables can then be used to iterate through the input. The last scan will only capture the ascii character and the integer and the return from sscanf will be 2.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct pair {
char ascii;
int integer;
};
int main( void) {
char input[] = "a1,b3,!0,t11, 2,,5,\\3,*4,34400,";
char comma = '\0';
char ascii = '\0';
int integer = 0;
int result = 0;
int loop = 0;
int length = 0;
int used = 0;
int add = 0;
int offset = 0;
struct pair *pairs = NULL;//so realloc will work on first call
struct pair *temp = NULL;
//assuming input will always end in 00, ( or ,00,)
//remove those three ( or 4 ??) characters
length = strlen ( input);
if ( length > 3) {
input[length - 3] = '\0';
}
while ( ( result = sscanf ( &input[offset], "%c%d%c%n"
, &ascii, &integer, &comma, &add)) >= 2) {//the last scan will only get two items
if ( ( temp = realloc ( pairs, ( used + 1) * sizeof ( *pairs))) == NULL) {
fprintf ( stderr, "problem allocating\n");
break;
}
pairs = temp;
pairs[used].ascii = ascii;
pairs[used].integer = integer;
//one more element was used
used++;
//the character following the integer should be a comma
if ( result == 3 && comma != ',') {
printf ( "format problem\n");
break;
}
//for the next iteration, add to offset
offset += add;
}
for ( loop = 0; loop < used; loop++) {
printf ( "ascii[%d] = %c ", loop, pairs[loop].ascii);
printf ( "value[%d] = %d\n", loop, pairs[loop].integer);
}
free ( pairs);
return 0;
}
Since you have figured out that you can just ignore the last 3 characters, using sscanf will be sufficient.
You can use sscanf to read one character (or getch functions), use sscanf to read an integer and finally even ignore one character.
Comment if you are having problems understanding how to do so.

Reading a list of characters and storing in an array

I am having issues with the following code and I cant figure out why out of loop is not being printed. With this code I want the program to ignore any spaces inputted by the user and after a space is inputted the number previously entered is stored in an array location. Like this I want 6 and 78 to be stored in 2 array locations not store them individually as 6 7 8.
This is my code:
while ((in=getchar()) != '0')
{
if (in == ' ')
{
printf("space\n ");
continue;
}
else
{
printf("assigning\n ");
input[i]=in;
}
i++;
}
printf("Out of Loop");
My output when inputting 5 6 78 is:
assigning
space
assigning
space
assigning
assigning
assigning
With this output I doubt whether 78 is being stored in one memory location.
I would really appreciate your help,Thankyou
C++:
std::vector<int> v;
std::string s;
int i;
std::getline( std::cin, s); // read full line with whitespaces
std::istringstream iss( s); // prepare to process the line
while( iss >> i) v.push_back( i); // read into i and push into vector if
// operator>> was successful
C:
int array[ 10];
int i = 0, retval;
while( i < 10 && ( retval = scanf( "%d", &array[ i++])) == 1) ;
if( i == 10) {
// array full
}
if( retval == 0) {
// read value not an integer. matching failure
}
if( retval == EOF) {
// end of file reached or a read error occurred
}
You are deciding character by character. Thus, you will only store single digits or ignore those digits.
You could store the whole numbers like this (extending your code):
bool currentNumberStarted = false;
int currentNumber = 0;
int idx = 0;
while ((in=getchar()) != '0')// you probably want '\0' instead of '0'
{
if (in == ' ')
{
if (currentNumberStarted)
{
input[idx]=currentNumber;
idx++;
currentNumberStarted = false;
}
printf("space\n ");
continue;
}
else
{
printf("assigning\n ");
currentNumberStarted = true;
currentNumber *= 10;
currentNumber += in;
}
}
printf("Out of Loop");
First of all I highly doubt that your while loop will ever end, even if you made that to '\0' ,Because you are using char variable to store input. Not strings, Only strings uses '\0' at the end,How can we enter '\0' from keyboard..???. even if you want to keep it as '0',you would alwasy have to enter 0 as last number to end the loop(which i think you dont want to.)
So the Solution is this:-
After Entering Numbers You will Hit ENTER key, which would generate a newline character '\n' so you have to check for new line character('\n'), And as you are using getchar() function, it will returns EOF (-1) at the end of input, so its important to check for it too.So you have to check for both '\n' and EOF at once in while loop.And at last you should also check for array index number(it should be less than 1) in which you are storing numbers.
I made some effort to make you understand the program in comments.
int main()
{
int i=0;
int input[10]={0}; //here only 10 integers can be entered(hence i should be i<10)
int in; //To store input character
int num=0; //To store number which is converted from character.
int new=1; //To check if new number is started 0=false 1=True.
int count=0;//This is just to know how many numbers entered,also used to print numbers at end.
while ((in=getchar()) != '\n' && (in!=EOF) && i<10)//should check for both '\n' and EOF and array index also
{
if (in == ' ')
{
printf("space\n ");
if(new==0) //if new Number is not started yet.
{
new=1; //Start of a New number.(a number entered after space)
i++; //As new number is started it should be stored in new array index.
}
continue; //if space is entered just go to begining
}
else
{
printf("assigning\n ");
num=in-48; //converts a character to number (ex:- converts '3' to 3)
input[i]=(input[i]*10)+num; //storing the number..This is important do a paper work to understand this step.
new=0; //still in same number(we are still processing same number)
}
}
printf("Out of Loop \n");
count=i+1; //This gives correct count of numbers entered
for(i=0;i<count;i++) //to print numbers.
printf("%d ",input[i]);
return 0;
}
OUTPUT:-
E:>example.exe
78 2 65 998 1
assigning
assigning
space
assigning
space
.
.
.
space
assigning
Out of Loop
78 2 65 998 1

intToStr recursively

This is a task from school, I am supposed to write a recursive function that will convert a given int to a string, I know I'm close but I can't point the missing thing in my code, hints are welcome.
void intToStr(unsigned int num, char s[])
{
if (num < 10)
{
s[0] = '0' + num;
}
else
{
intToStr(num/10, s);
s[strlen(s)] = '0' + num%10;
}
}
Edit: my problem is that the function only works for pre initialized arrays, but if I let the function work on an uninitialized function it will not work.
Unless your array is zero-initialized, you are forgetting to append a null terminator when you modify it.
Just add it right after the last character:
void intToStr(unsigned int num, char s[])
{
if (num < 10)
{
s[0] = '0' + num;
s[1] = 0;
}
else
{
intToStr(num/10, s);
s[strlen(s)+1] = 0; //you have to do this operation here, before you overwrite the null terminator
s[strlen(s)] = '0' + num%10;
}
}
Also, your function is assuming that s has enough space to hold all the digits, so you better make sure it does (INT_MAX is 10 digits long I think, so you need at least 11 characters).
Andrei Tita already showed you the problem you had with the NULL terminators. I will show you an alternative, so you can compare and contrast different approaches:
int intToStr(unsigned int num, char *s)
{
// We use this index to keep track of where, in the buffer, we
// need to output the current character. By default, we write
// at the first character.
int idx = 0;
// If the number we're printing is larger than 10 we recurse
// and use the returned index when we continue.
if(num > 9)
idx = intToStr(num / 10, s);
// Write our digit at the right position, and increment the
// position by one.
s[idx++] = '0' + (num %10);
// Write a terminating NULL character at the current position
// to ensure the string is always NULL-terminated.
s[idx] = 0;
// And return the current position in the string to whomever
// called us.
return idx;
}
You will notice that my alternative also returns the final length of the string that it output into the buffer.
Good luck with your coursework going forward!