Forum Archive

Go Back   3D Realms Forums > Archives > General Messages > Programming Forum

 
 
Thread Tools
Old 03-21-2009, 12:06 AM   #1
MusicallyInspired

MusicallyInspired's Avatar
Possible to convert/combine two separate digit char variables into one int variable?
I have two char variables: firstdigit and seconddigit. Each one has a digit as its ASCII representation. So far my plan has been to try and copy both "numbers" into a char array called bothdigits[] and then try to convert that into a double-digit value in an int variable. So far I'm not having any luck at all as I don't think the atoi() function supports converting char arrays (strings) to integer values with more than one digit.

Is what I'm attempting even possible?
__________________
Roland SC-55 Music Packs Website
- MediaFire mirror for Duke3D expansions
More SC-55 music packs coming soon...
Last edited by MusicallyInspired; 03-21-2009 at 12:10 AM.
MusicallyInspired is offline  
Old 03-21-2009, 12:18 AM   #2
Jiminator

Jiminator's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
What the heck are you trying to do? Sounds pretty convoluted. And why won't the atoi function work? it should if bothdigits is terminated with a 0. Or rather than deal with a function call you can say (bothdigits[0]-48)*10+(bothdigits[1]-48)
__________________
big badass nasty weapons here....
Jiminator is offline  
Old 03-21-2009, 07:30 AM   #3
cyborg

cyborg's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
firstDigit << 8 + secondDigit
__________________
You lose.
cyborg is offline  
Old 03-21-2009, 08:09 AM   #4
MusicallyInspired

MusicallyInspired's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
I'm trying to read numbers from a file. Works fine up until the point where there is more than 9 and then I don't know how to read a double-digit number and store it as an int value in an array along with the other values. This is the only thing I could come up with.

Cyborg, will that work in a non-C++ source?
__________________
Roland SC-55 Music Packs Website
- MediaFire mirror for Duke3D expansions
More SC-55 music packs coming soon...
MusicallyInspired is offline  
Old 03-21-2009, 08:58 AM   #5
cyborg

cyborg's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
The semantics of the << operator is "bit shift right by...". Bit shifting right is the equivalent of multiplying by powers of 2. << 8 is equivalent to * 256. Given that you're saying you're using atoi and this is a C library function then you have the << operator available.

Of course reading this again I don't know why you think "the atoi() function [does not] [support] converting char arrays (strings) to integer values with more than one digit."

Simply put: atoi("99") == 99

Post your code.
__________________
You lose.
cyborg is offline  
Old 03-21-2009, 12:19 PM   #6
MusicallyInspired

MusicallyInspired's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
You're right. It should work. But converting the char array double digit number from the file to an int is still not working for me.

Here's how it goes. I have an external file that contains numbers encased in square brackets ("[]'s") from 0 to a max of 76 if there are that many. I want my program to search for all these numbers and print them on the screen one after the other (along with a \n character so they're not all bunched together). I don't want to post the source right now because it's pretty much a mess. Basically what I have is an if statement comparing whether or not the current character being looked at from the file is a '[' and if it is to compare whether or not the the character after the next character is a ']' and if it is to go back in between them and copy the character there to a an int array called menu[]. If it doesn't find the ']' character it checks whether the next character after THAT is the ']' (to see if there are two digits in between the square brackets) and if it is then it goes back two characters and copies each of the digits into firstdigit and seconddigit. Then I'm trying to combine both of those char variables into one char array (though I guess I can just make a char array called digits[2] and assign their values to each digit without using firstdigit and seconddigit) and then convert that to an int value with bothdigits=atoi(digits);. It's not working, though.
__________________
Roland SC-55 Music Packs Website
- MediaFire mirror for Duke3D expansions
More SC-55 music packs coming soon...
MusicallyInspired is offline  
Old 03-21-2009, 12:43 PM   #7
Jiminator

Jiminator's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
Quote:
Originally Posted by cyborg View Post
firstDigit << 8 + secondDigit
won't work on many levels, he said ascii digits, that means subtracting 48 from each to get to the basic values. second problem is you have base 10 numbers and you are doing a base 2 shift by 8 digits, the result is similar to asc(first) * 256 + asc(second)

MI: anyways, not sure why this is necessary, how about you post some source code with the problem.

EDIT: just saw your last post

---------- Post added at 12:43 PM ---------- Previous post was at 12:28 PM ----------

if you are just printing them then there is no need to convert...

something like (assuming you have allocated memory and read the file into memory):
this is just pseudocode, not code that will work without changes
Code:
for (c = 0; c<length - 2; c++)
if (file[c]='[')
 if (file[c+2]==']' || c<length - 3 && file[c+3]==']'){
    n = file[c+1] - '0';
    if (file[c+2]!=']')
       n = n * 10 + (file[c+2] - '0');
    //print or whatever
 }
__________________
big badass nasty weapons here....
Jiminator is offline  
Old 03-21-2009, 02:22 PM   #8
cyborg

cyborg's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
Quote:
You're right. It should work. But converting the char array double digit number from the file to an int is still not working for me.
Then the first question you should ask is not:

"Why is this library function that has existed for thirty odd years not working?"

But:

"How have I screwed up?"

Are your chars really what you expect them to be? Are you sure you've given the function the correct inputs? Etc...

Now, onto the specifics.

Quote:
I have an external file that contains numbers encased in square brackets ("[]'s") from 0 to a max of 76 if there are that many.
A maximum of 76 numbers.

Quote:
I want my program to search for all these numbers and print them on the screen one after the other (along with a \n character so they're not all bunched together).
Two problems:
1) Populating an array of numbers from a file
2) Printing an array of numbers

Quote:
Basically what I have is an if statement comparing whether or not the current character being looked at from the file is a '[' and if it is to compare whether or not the the character after the next character is a ']' and if it is to go back in between them and copy the character there to a an int array called menu[]. If it doesn't find the ']' character it checks whether the next character after THAT is the ']' (to see if there are two digits in between the square brackets) and if it is then it goes back two characters and copies each of the digits into firstdigit and seconddigit. Then I'm trying to combine both of those char variables into one char array (though I guess I can just make a char array called digits[2] and assign their values to each digit without using firstdigit and seconddigit) and then convert that to an int value with bothdigits=atoi(digits);.
Parse a text stream of the form '[xx]' or '[x]' to extract a number xx or x.

The algorithm you're describing sounds pretty unwieldy so it's not surprising your code problem looks a mess.

Code:
#include <stdio.h>
int main() {
  int[76] menu;

  // Parse file
  FILE *fp = fopen("file");
  char c;
  int state = 0;
  char[3] buffer;
  int bufpointer = 0;
  int i;
  while (c = fgetc(fp) != EOF) {
    switch(state) {
       case 0:
         if (c == '[') { state = 1; } break; // Start of number
       case 1:
         if (bufpointer==2) { // Too large, cannot parse this
           state = 0; break;
         }
         if (c != ']' && isdigit(c)) { // Buffer digit
           buffer[bufpointer++] = c;
         }
         if (c == ']' && bufpointer > 0) { // Complete number
           buffer[bufpointer] = 0;
           menu[i++] = atoi(buffer);
           bufpointer = 0;
           state = 0;
         }
    }
  }

  // Print numbers
  int k;
  for (k = 0; k < i; k++) {
    printf("%d\n", menu[k]);
  }
}
Assuming that you care nothing of any other potential characters in your file.

Disclaimer: code not compiled or tested. At least one obvious flaw I can see. Left as an exercise to the reader.
__________________
You lose.
cyborg is offline  
Old 03-21-2009, 05:05 PM   #9
Wooloomooloo

Wooloomooloo's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
Wouldn't it be easier to just use fscanf? Or am I missing something?
__________________
"I'm an engineer, not a normal person." -Dilbert
Wooloomooloo is offline  
Old 03-22-2009, 12:33 PM   #10
theHunted
Re: Possible to convert/combine two separate digit char variables into one int variab
Quote:
Originally Posted by Wooloomooloo View Post
Wouldn't it be easier to just use fscanf? Or am I missing something?
You are missing the point that the OP is obviously not as much of a coding guru as you are and so giving a tiny example of use would've helped a lot more.
__________________
M:I - New Dawn
a Max Payne 2 modification
theHunted is offline  
Old 03-22-2009, 03:03 PM   #11
MusicallyInspired

MusicallyInspired's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
Quote:
Originally Posted by Jiminator View Post
if you are just printing them then there is no need to convert...

something like (assuming you have allocated memory and read the file into memory):
this is just pseudocode, not code that will work without changes
Code:
for (c = 0; c<length - 2; c++)
if (file[c]='[')
 if (file[c+2]==']' || c<length - 3 && file[c+3]==']'){
    n = file[c+1] - '0';
    if (file[c+2]!=']')
       n = n * 10 + (file[c+2] - '0');
    //print or whatever
 }
Thanks! That looks like it makes a lot more sense than my idea.

Quote:
Originally Posted by cyborg View Post
Then the first question you should ask is not:

"Why is this library function that has existed for thirty odd years not working?"

But:

"How have I screwed up?"
I'm not that pretentious. That IS what I was asking. I've said I was new to programming numerous times in this forum.

Quote:
Two problems:
1) Populating an array of numbers from a file
2) Printing an array of numbers
Ok, why is that a problem?

Quote:
Parse a text stream of the form '[xx]' or '[x]' to extract a number xx or x.

The algorithm you're describing sounds pretty unwieldy so it's not surprising your code problem looks a mess.

Code:
#include <stdio.h>
int main() {
  int[76] menu;

  // Parse file
  FILE *fp = fopen("file");
  char c;
  int state = 0;
  char[3] buffer;
  int bufpointer = 0;
  int i;
  while (c = fgetc(fp) != EOF) {
    switch(state) {
       case 0:
         if (c == '[') { state = 1; } break; // Start of number
       case 1:
         if (bufpointer==2) { // Too large, cannot parse this
           state = 0; break;
         }
         if (c != ']' && isdigit(c)) { // Buffer digit
           buffer[bufpointer++] = c;
         }
         if (c == ']' && bufpointer > 0) { // Complete number
           buffer[bufpointer] = 0;
           menu[i++] = atoi(buffer);
           bufpointer = 0;
           state = 0;
         }
    }
  }

  // Print numbers
  int k;
  for (k = 0; k < i; k++) {
    printf("%d\n", menu[k]);
  }
}
Assuming that you care nothing of any other potential characters in your file.

Disclaimer: code not compiled or tested. At least one obvious flaw I can see. Left as an exercise to the reader.
Thank you! I'll see what I can do with this.

Quote:
Originally Posted by theHunted View Post
You are missing the point that the OP is obviously not as much of a coding guru as you are and so giving a tiny example of use would've helped a lot more.
An example would have proved useful, yes. Why would fscanf work better? Does it search for specific things throughout the whole file like that?

I suppose I should state the true intent of why I'm doing this. I'm just trying to get the numbers to print on screen as an exercise for working with external files. My ultimate goal is for my DOS menu I was describing in another thread. I'm trying to make my program read a "menu.cfg" file. My menu program will take a maximum of 76 menus. I want each menu's attributes and menu items to be beneath its number so it would look something like this:

Code:
[0]
title="MAIN MENU"
menu_item1="Adventure Games"
type=submenu
gotomenu=1

menu_item2="Duke Nukem 3D"
type=exec
cdwarn=false
drive="d"
path="\duke3d"
exec="duke3d"

[1]
title="ADVENTURE GAMES"
menu_item1="King's Quest VI"
type=exec
cdwarn="Insert the King's Quest VI CD"
drive="d"
path="\sierra\kqc\kq6d"
exec="sierra resource.cfg"
So I'm trying to make my program search for each menu number and apply each attribute to the menu being displayed and what each menu item does. Hopefully that clears some things up.
__________________
Roland SC-55 Music Packs Website
- MediaFire mirror for Duke3D expansions
More SC-55 music packs coming soon...
MusicallyInspired is offline  
Old 03-22-2009, 04:41 PM   #12
Wooloomooloo

Wooloomooloo's Avatar
Goofy Re: Possible to convert/combine two separate digit char variables into one int variab
Okay, here's some sample code I just tested:

Code:
#include <stdio.h>

int main()
{
	FILE* in;
	int number;
	int i;

	in = fopen( "test.txt", "r" );
	if ( in == NULL )
	{
		printf( "Could not open test.txt\n" );
		return 0;
	}

	for ( i = 0; i < 10; i++ )
	{
		fscanf( in, "[%d]", &number );
		printf( "Read number %d\n", number );
	}

	fclose( in );
	return 0;
}
It reads 10 numbers from a file. My test input was something like "[100][20][333333][44][55][62][1117][82][91111][10]". Not exactly what you need, but it should save you the trouble of messing with digits and string to integer conversion.

The arguments to fscanf are the previously opened FILE to read from, a format string and a variable number of destination addresses that is specified by the format string.

The format string ("[%d]" in the example) is composed of control characters (which are preceded by a % sign), whitespace chars and non-whitespace chars. Non-whitespace chars like '[' and ']' are read by the function and ignored; 'd' is a control char since it comes after a single % sign and it tells the function to match as much of the current input as possible to a decimal integer. As far as I remember any whitespace (including tabs and new line chars) in the control string matches any whitespace in the input.

In the above code, I'm only reading one element at a time (a decimal integer), so I pass fscanf the address of the variable where the integer should go. If I were to read two integers with a single fscanf call, my control string would have two "%d" and two address arguments after it.

The function returns the number of elements that were read.

There are many other control characters that allow you to read floating point numbers, chars, string, octal and hex integers and so on. Google it

Hope this helps.

Disclaimer: I'm not a code guru, so all that stuff I just posted may not be 100% correct, especially the part about whitespace handling in scanf and friends, which I remember being a pain. :P
__________________
"I'm an engineer, not a normal person." -Dilbert
Wooloomooloo is offline  
Old 03-24-2009, 11:24 AM   #13
MusicallyInspired

MusicallyInspired's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
Many thanks. Now I just have one other question. I only want it to scan for 1 or two digit numbers between "[]'s" as one of the command line parameters for the executable of one of the games has [330] to define which port the MIDI device is using. Obviously I don't want my program to find this number and think it's a menu number. How would I go about making it scan for just 1 or 2 digit numbers and no more, since the way you're describing it sounds like it'll search for integers of any number of digits?

Also, I want my program to figure out how many menus there are (how many numbers encased in "[]'s") and using your code assign each value to an array. I can't just put a number like "10" in the for(;;) statement for how long I want the loop to go on for because the number could be different every time depending on how many menus are defined in menu.cfg.

EDIT: I just tried your code and it doesn't work. It just returns a bunch of negative numbers in the hundreds when in reality it's numbers between 0 and 20, in my menu.cfg file. Also I threw in a variable called "nummenus" and told it to increment itself every time went through the loop and then after the loop was finished to show the value of nummenus and the result was "-12." What's up with that?

EDIT 2: Cyborg, your code produces an almost unending slew of numbers with values in the thousands in the negative and positive ranges as well as every now and then showing hundreds of zeros and finally ends with 0, 1, 2, 3, and 4.
__________________
Roland SC-55 Music Packs Website
- MediaFire mirror for Duke3D expansions
More SC-55 music packs coming soon...
Last edited by MusicallyInspired; 03-24-2009 at 12:15 PM.
MusicallyInspired is offline  
Old 03-24-2009, 12:18 PM   #14
Bad Sector

Bad Sector's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
The answer for the original question should be:

number = (firstdigit - '0')*10 + (seconddigit - '0')

Example working program:
Code:
#include <stdlib.h>

int main()
{
    char firstdigit = '3';
    char seconddigit = '4';

    int number = (firstdigit - '0')*10 + (seconddigit - '0');

    printf("number is %i\n", number);
    return 0;
}
I'm not sure i understood the second question, please give some examples.
Bad Sector is offline  
Old 03-24-2009, 12:56 PM   #15
Qbix
DOSBox Advisor

Qbix's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
read one line at the time and only parse the [%d] stuff if the first character is a [ ?
Qbix is offline  
Old 03-24-2009, 03:39 PM   #16
theHunted
Re: Possible to convert/combine two separate digit char variables into one int variab
Quote:
Originally Posted by Qbix View Post
read one line at the time and only parse the [%d] stuff if the first character is a [ ?
Either that or check the return value of fscanf. I've only run a quick test with scanf, but it returns 1 in case the format string has been matched successfully and 0 in case it hasn't. So just do the processing in case fscanf returns 1.

Quote:
Originally Posted by MusicallyInspired View Post
Many thanks. Now I just have one other question. I only want it to scan for 1 or two digit numbers between "[]'s" as one of the command line parameters for the executable of one of the games has [330] to define which port the MIDI device is using. Obviously I don't want my program to find this number and think it's a menu number. How would I go about making it scan for just 1 or 2 digit numbers and no more, since the way you're describing it sounds like it'll search for integers of any number of digits?

Also, I want my program to figure out how many menus there are (how many numbers encased in "[]'s") and using your code assign each value to an array. I can't just put a number like "10" in the for(; statement for how long I want the loop to go on for because the number could be different every time depending on how many menus are defined in menu.cfg.

EDIT: I just tried your code and it doesn't work. It just returns a bunch of negative numbers in the hundreds when in reality it's numbers between 0 and 20, in my menu.cfg file. Also I threw in a variable called "nummenus" and told it to increment itself every time went through the loop and then after the loop was finished to show the value of nummenus and the result was "-12." What's up with that?

EDIT 2: Cyborg, your code produces an almost unending slew of numbers with values in the thousands in the negative and positive ranges as well as every now and then showing hundreds of zeros and finally ends with 0, 1, 2, 3, and 4.
I don't think you can restrict fscanf to only process 2 digit numbers the way you want. But that doesn't matter imo. After fscanf has done it's job on a line you'll just want to check that the read number is < 100 and thus only 2 digits.

As for the increment counter that returned -12 at the end. Did you make sure to initialize the variable to 0 when declaring it? (e.g. int counter = 0; instead of int counter
__________________
M:I - New Dawn
a Max Payne 2 modification
theHunted is offline  
Old 03-24-2009, 04:11 PM   #17
Jiminator

Jiminator's Avatar
Re: Possible to convert/combine two separate digit char variables into one int variab
gotta love c & c++, pointers and references, memory allocations, such a raw, powerful and dirty language. used to be fun writing and debugging c code.
__________________
big badass nasty weapons here....
Jiminator is offline  
Old 03-24-2009, 09:19 PM   #18
Wooloomooloo

Wooloomooloo's Avatar
Goofy Re: Possible to convert/combine two separate digit char variables into one int variab
Quote:
Originally Posted by MusicallyInspired View Post
Many thanks. Now I just have one other question. I only want it to scan for 1 or two digit numbers between "[]'s" as one of the command line parameters for the executable of one of the games has [330] to define which port the MIDI device is using.
Use delimiters (like the quotes you used in your example) to enclose anything that should be passed verbatim to the command line. Once your code finds a delimiter, make it simply read everything until another delimiter is found, so you won't have to worry about these cases.

Quote:
Also, I want my program to figure out how many menus there are (how many numbers encased in "[]'s") and using your code assign each value to an array. I can't just put a number like "10" in the for( ; ; ) statement for how long I want the loop to go on for because the number could be different every time depending on how many menus are defined in menu.cfg.
You're better off using a while loop that stops when no more data can be read from the config file.

Quote:
EDIT: I just tried your code and it doesn't work. It just returns a bunch of negative numbers in the hundreds when in reality it's numbers between 0 and 20, in my menu.cfg file. Also I threw in a variable called "nummenus" and told it to increment itself every time went through the loop and then after the loop was finished to show the value of nummenus and the result was "-12." What's up with that?
Did you try it with a file formatted like the example I posted? fscanf read formatted input; if you throw anything that does not follow the format string at it, it will fail and return 0, since it could not read any elements from the input.
__________________
"I'm an engineer, not a normal person." -Dilbert
Last edited by Wooloomooloo; 03-24-2009 at 09:23 PM.
Wooloomooloo is offline  
 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -6. The time now is 06:02 AM.

Page generated in 0.14788389 seconds (100.00% PHP - 0% MySQL) with 15 queries

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.

Website is 1987-2014 Apogee Software, Ltd.
Ideas and messages posted here become property of Apogee Software Ltd.