How to read data from file into an array - c++

I have this program to take properties from a data file and input them into calculations into the program. this is my code at the moment but it isn't taking any values into it.. any help is appreciated
float woodcharacStrength(){
myInfile.open ("strength_classes.txt"); //inputs external file that contains characteristic values for forces parallel to grain.
for (row = 0; row<3; row++)
for (col = 0; col<18; col++) //condition to only read certain rows and columns of the input file
{
myInfile >> arraylocation[row][col]; //used to define each value of the array
}
switch(woodType){
case 'A':
case 'a': ftk = arraylocation[0][0]; fck = arraylocation[1][0];break;
case 'B':
case 'b': ftk = arraylocation[0][1]; fck = arraylocation[1][1];break;
case 'C':
case 'c': ftk = arraylocation[0][2]; fck = arraylocation[1][2];break;
case 'D':
case 'd': ftk = arraylocation[0][3]; fck = arraylocation[1][3];break;
case 'E':
case 'e': ftk = arraylocation[0][4]; fck = arraylocation[1][4];break;
case 'F':
case 'f': ftk = arraylocation[0][5]; fck = arraylocation[1][5];break;
case 'G':
case 'g': ftk = arraylocation[0][6]; fck = arraylocation[1][6];break;
case 'H':
case 'h': ftk = arraylocation[0][7]; fck = arraylocation[1][7];break;
case 'I':
case 'i': ftk = arraylocation[0][8]; fck = arraylocation[1][8];break;
case 'J':
case 'j': ftk = arraylocation[0][9]; fck = arraylocation[1][9];break;
case 'K':
case 'k': ftk = arraylocation[0][10]; fck = arraylocation[1][10];break;
case 'L':
case 'l': ftk = arraylocation[0][11]; fck = arraylocation[1][11];break;
case 'M':
case 'm': ftk = arraylocation[0][12]; fck = arraylocation[1][12];break;
case 'N':
case 'n': ftk = arraylocation[0][13]; fck = arraylocation[1][13];break;
case 'O':
case 'o': ftk = arraylocation[0][14]; fck = arraylocation[1][14];break;
case 'P':
case 'p': ftk = arraylocation[0][15]; fck = arraylocation[1][15];break;
case 'Q':
case 'q': ftk = arraylocation[0][16]; fck = arraylocation[1][16];break;
case 'R':
case 'r': ftk = arraylocation[0][17]; fck = arraylocation[1][17];break;
}
cout <<"The ftk value is: "<< ftk<< endl<<"The fck value is: "<< fck<<endl;
return ftk;
return fck;
myInfile.close();
}

for (row = 0; row<3; row++) //you have no open and close braces for this for loop

Suggestions:
1) Look up std::toupper or std::tolower so you don't have to use both upper and lower case letters in your case statements.
2) Create a index by subtracting letters:
unsigned int index = std::toupper(woodType) - 'A';
ftk = arraylocation[0][index];
fck = arraylocation[1][index];
3) A function can only return one value: ftk or fck.
If you want to return more than one value, pass them by reference or put them in a structure and return a copy of the modified structure.
4) No execution flows after a return statement, so your code will never execute the 2nd return statement or the fclose.

Related

How to convert char into int in a function?

poziomy= char;
pionowy= digit; ( no problems with this one)
So I need to convert char into a digit in function but obviusly I cannot do char=int, so I dont know how to pass on the converted char into digit properly.
I guees i can do two functions but maybe there is an easier way?
I thought of making a new variable poziomy_c but I dont know how to pass it to Ruch_gracza()
int Convert_digit (int cyfra)
{
switch (cyfra)
{
case 10: return 0;break;
case 9: return 1;break;
case 8: return 2;break;
case 7: return 3;break;
case 6: return 4;break;
case 5: return 5;break;
case 4: return 6;break;
case 3: return 7;break;
case 2: return 8;break;
case 1: return 9;break;
}
}
int Convert_letter (char literka)
{
switch (literka)
{
case 'A': return 0; break;
case 'B': return 1; break;
case 'C': return 2; break;
case 'D': return 3; break;
case 'E': return 4; break;
case 'F': return 5; break;
case 'G': return 6; break;
case 'H': return 7; break;
case 'I': return 8; break;
case 'J': return 9; break;
}
}
void Conwert(int &pionowy, char poziomy)
{
pionowy=Convert_digit(pionowy);
int poziomy_c;
poziomy_c=Convert_letter (poziomy);
}
void Ruch_gracza1 (int plansza[10][10])
{
int pionowy ;
char poziomy;
cout << "wprowadz wspolrzedne pola na ktorym lezy pion który chcesz ruszyc ( w pionie , potem w poziomie)" << endl;
cin >> pionowy >> poziomy;
Conwert (pionowy,poziomy);
cout << pionowy << endl;
cout << poziomy << endl;
}
You can use char arithmetic to make this a whole lot easier. Since 'A' to 'Z' will be contiguous in ASCII/Unicode, you can do literka - 'A' to get how far literka is from A (which is what your switch is doing):
int Convert_letter (char literka) {
if(!std::isalpha(literka)) { return literka; } // Not a letter
return std::toupper(literka) - 'A';
}
Or if you want a more robust solution to cover even less common character encodings:
int Convert_letter (char literka) {
if(!std::isalpha(literka)) { return literka; } // Not a letter
std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
return std::distance(std::begin(alphabet), std::find(std::begin(alphabet), std::end(alphabet), literka));;
}
Convert_digit will look similar (except with std::isdigit instead of std::isalpha).
You can do as
char c = 'B';
int digit = c - 'A';
return digit;
You need some knowledge about the ASCII table and data type in C++.
Simply, a char is an integer from -128 ... 127. If you declare a char variable name ch like this:
char ch = 'B';
C++ will understand that ch = 66 (look at ASCII table). So that we can do arithmetic operator with ch like an integer variable.
ch - 'A'; // result 1, because 'A' = 65
ch - 65; // same result with ch - 'A'
Finally, you can write your function like this:
int functionChar2Int(char x){
return x - 'A';
}

if statement doesn't work in the block of switch?

I wrote a simple function as the following, but it does not work as expected, in C++, the if statement doesn't work in the block of switch?
void any2ten(string origin, int type)
{
if(! (type == 2 || type == 8 || type == 16))
{
cout << "unsupport this " << endl;
return;
}
int result = 0;
for (int index = 0; index < origin.length(); index++)
{
int tmp = 0;
switch (origin[index])
{
if (type == 16)
{
case 'F':
case 'f':
tmp = 15 * pow(type, index); break;
case 'E':
case 'e':
tmp = 14 * pow(type, index); break;
case 'D':
case 'd':
tmp = 13 * pow(type, index); break;
case 'C':
case 'c':
tmp = 12 * pow(type, index); break;
case 'B':
case 'b':
tmp = 11 * pow(type, index); break;
case 'A':
case 'a':
tmp = 10 * pow(type, index); break;
case '9':
tmp = 9 * pow(type, index); break;
case '8':
tmp = 8 * pow(type, index); break;
}
if (type == 8 || type == 16)
{
case '7':
tmp = 7 * pow(type, index); break;
case '6':
tmp = 6 * pow(type, index); break;
case '5':
tmp = 5 * pow(type, index); break;
case '4':
tmp = 4 * pow(type, index); break;
case '3':
tmp = 3 * pow(type, index); break;
case '2':
tmp = 2 * pow(type, index); break;
}
case '1':
tmp = 1 * pow(type, index); break;
case '0':
tmp = 0; break;
default:
cout << "wrong character has got" << endl;
return;
break;
}
result += tmp;
}
cout << result << endl;
}
while I test the function as any2ten("aa", 8), the result is 90 rather than wrong character.
is there anything wrong?
The if statement works fine in the block of a switch, you've just put it in a place where it never gets executed. The switch statement jumps to the corresponding case, that is its purpose. Whatever it jumps to, it will skip over the if, so the if never executes.
If you were to add code to make it possible to jump to between the switch and the if, then the if would execute normally. You could do this with a loop of any kind or a goto.
A default is only taken if no case is matched. Otherwise, the switch jumps to the matching case.
The switch statement doesn't work the way you imagine that it works. The way it behaves is not as a substitute of an if-else if-else, but somewhat differently.
Upon encountering the switch the process will jump to the code following the correct case. This means that you actually completely skip the execution of the if that you have placed there.
And yes, it does look weird, since you assume that because you have the curly braces you must execute if condition or not enter into them at all, but this is simply not the case.
Well the placement of your if-statement doesn't really make sense. The switch-statement jumps to the corresponding case and then exists, hence your if-statement won't be executed. And I wouldn't recommend to use goto, cause it's considered as a bad-practice.

Counting vowels, consonants, numbers and other symbols in a string

I'm trying to count how many vowels/consonants/numbers/other symbols there are in a string.
#include <stdio.h>
#include <string.h>
int main(void)
{
int cons = 0, vow = 0, num = 0, oth = 0;
int i, length;
char str[100];
printf("Input a string with no space : ");
scanf("%s", &str);
printf("=====================================\n");
length = strlen(str);
for(i = 0; i < length; i++)
{
switch(str)
{
case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': case 'A':
case 'E': case 'I': case 'O': case 'U': case 'Y':
vow++;
break;
case 'b': case 'c': case 'd': case 'f': case 'g': case 'h': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': case 'r':
case 's': case 't': case 'v': case 'w': case 'x': case 'z':
case 'B': case 'C': case 'D': case 'F': case 'G': case 'H': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'V': case 'W': case 'X': case 'Z':
cons++;
break;
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
case 9:
num++;
break;
default:
oth++;
break;
}
}
printf("%s\n", str);
printf("Number of consonants: %d\n", cons);
printf("Number of vowels: %d\n", vow);
printf("Number of numbers: %d\n", num);
printf("Number of other symbols: %d\n", oth);
}
I know that my problem lacks in my 'switch' but I don't really know what to put there. Should I put something else that the name of my string?
There are two common ways of accessing all characters in a C string:
Using an index - in your case, that would mean str[i]
Using a pointer - this would let you avoid strlen call.
Here is how the second approach would look:
for (char* p = str ; *p != '\0' ; p++) {
switch (*p) {
...
}
}
Note that the length and the index i are no longer necessary, because the loop will terminate when the pointer p reaches null terminator.
Also note that scanf("%s", &str); is not safe - you need to tell scanf how big is your buffer:
int numScanned = scanf("%99s", str);
This would prevent buffer overruns. Note the use of 99 for a 100-char buffer: this is done to reserve one char for null terminator character. Also note that you should not place & in front of str, because the array is already treated like a pointer when you are calling a function.
You should check numScanned to be equal to 1 to detect possible failures in scanf.

can not convert parameter 1 from int into &int

Lets imagine I have got functions:
int switcherINT(char &c){
switch (c){
case '1': return 1; break;
case '2': return 2; break;
case '3': return 3; break;
case '4': return 4; break;
case '5': return 5; break;
case '6': return 6; break;
case '7': return 7; break;
case '8': return 8; break;
case '9': return 9; break;
case '0': return 0; break;
default: return err;
}
}
char switcherCHAR(int &c){
switch (c){
case 1: return '1'; break;
case 2: return '2'; break;
case 3: return '3'; break;
case 4: return '4'; break;
case 5: return '5'; break;
case 6: return '6'; break;
case 7: return '7'; break;
case 8: return '8'; break;
case 9: return '9'; break;
case 0: return '0'; break;
default: return errCH;
}
}
and I am trying to compute nest expression:
c.str[i] = switcherCHAR(switcherINT(pthis->str[pthis->size-i-1])-switcherINT(pb->str[pb->size-i-1])-loc);
where
longMath *pthis(this),*pb(&b);
longMath c;
class longMath{
protected:
char* str;
int size;
protected:
........
compiler says:
"can not convert parameter 1 from int into &int"
Haw can I solve this problem?
The expression that you've given as an argument to switcherCHAR gives you a temporary int. You cannot pass a temporary as a reference - unless you make the reference const. Just change switcherCHAR to take a const int& (and while you're at it, make switcherINT take a const char&). However, this are very simple types and you're probably better off just taking them by value. So change them to take just int and char.
Nonetheless, your functions are pretty strange. It is very easy to convert between a number x and it's char counterpart just by doing '0' + x. The numerical digit characters are guaranteed to be in consecutive order. So if you take the value of '0' and add, lets say, 5, you will get the value of the character '5'.
It would be much better to use functions like this:
int switcherINT(const char &c) {
return (c >= '0' && c <= '9') ? c - '0' : err;
}
char switcherCHAR(const int &c) {
return (c >= 0 && c <= 9) ? '0' + c : errCH;
}

int or char enum to int , not ASCII

I'm doing a poker game and have hit a wall. Any help would be great.
I have 12 card values. The values are chars either 2-9 or TJQKA (enumed below). I need to pass them to an int array such that their value is what gets passed (whether int value or enum value) instead of their ASCII.
for the example below, I want:
val[5] = {2,5,10,12,11}
instead of:
val[5] = {50,53,84,81,74}
enum cardvalues {T=10 , J , Q , K , A}
int val[5];
string value = "25TQJ";
for (int i = 0; i < 5; i++)
{
val[i] = value[i];
}
I would highly recommend using a map rather than an enum.
map<char,int> myCardMap;
myCardMap['T'] = 10;
...
val[i] = myCardMap[value[i]];
You'll need a conversion function:
int to_card(const char v)
{
switch(v)
{
case '2': return 2;
case '3': return 3:
// etc...
case 'T': return 10;
case 'J': return 11;
// etc...
}
Then in your loop:
val[i] = to_card(value[i]);
Make an std::map with ascii values in key and enum values in value
std::map<char, int> asciiMap;
asciiMap['T'] = 10;
asciiMap['J'] = 11;
//etc....
and then match the characters with the map
Generally you would need to convert the values from char to int. Here's the easiest way.
int convert_from_char(char c) {
if (c >= '2' && c <= '9') return (int)(c - '0');
else {
switch(c) {
case 'T': return (int)T;
case 'J': return (int)J;
case 'Q': return (int)Q;
case 'K': return (int)K;
case 'A': return (int)A;
default:
/* your program is borked. */
exit(1);
}
}
}
Then change your loop
for (int i = 0; i < 5; ++i)
val[i] = convert_from_char(value[i]);
I would suggest reconsidering using enums to represent cards, though. It will be easier in the long run just to make your own type, or use integers.
There is no way to directly convert from an enum symbol to the corresponding integer in C++ at runtime (obviously the compiler can do this at compile time). You may need to write a small helper function:
int card_value(char c) {
if (isdigit(c)) {
return c - '0';
} else {
switch (c) {
case 'T': return 10;
case 'J': return 11;
case 'Q': return 12;
case 'K': return 13;
case 'A': return 14;
default:
// whatever error handling here, such as:
return -1;
}
}
}
I suggest a switch:
switch (value[i]) {
case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
val[i] = atoi(value[i]);
break;
case 'T':
val[i] = 10;
break;
case 'J':
val[i] = 11;
break;
case 'Q':
val[i] = 12;
break;
case 'K':
val[i] = 13;
break;
case 'A':
val[i] = 14;
break;
default:
printf("Invalid character passed\n");
}
Create a function that will take a char argument (the ASCII card value, such as 'J') and return its numerical value. You might find the isdigit function and switch statement helpful.
If im understanding you correctly, you want to convert the string into card values (although for some reason you have the ace as 13 - id be tempted to say use 1 as the ace, although i can see you logic for it in a poker game).
Just using an enum wont help as at runtime you dont really have the information you need. An enum is a compile time concept mainly to assist the programmer and to handle checking.
There are many way to do what you want, you could have an array of index to char or a two entry array of char and value. For ease of alterations i would go with the following
typedef struct
{
char m_cCharacter;
int m_nValue;
} LOOKUP;
LOOKUP lookup_data[] = {
{ "2", 2 },
{ "3", 3 },
{ "4", 4 },
{ "5", 5 },
{ "6", 6 },
{ "7", 7 },
{ "8", 8 },
{ "9", 9 },
{ "T", 10 },
{ "J", 11 },
{ "Q", 12 },
{ "K", 13 },
{ "A", 14 }
};
int GetCharacter(char c)
{
int retval = -1; // Invalid
for(int i = 0; i < 13; i++)
{
if ( lookup_data[i].m_cCharacter == c )
{
retval = lookup_data[i].m_nValue;
break;
}
}
return retval;
}
for (int i = 0; i < 5; i++)
{
val[i] = GetCharacter(value[i]);
}
There are better ways with STL, and you should have more error checking and length of array detections, but hopefully you get the idea. You could use the enum in the lookup such as
{ "T", T },
If you preferred. Btw - i havent compiled this code so it probably wont build ;)
Try building a static array of size 256 such that the following gives the right answer:
for (int i = 0; i < 5; i++)
{
val[i] = AsciiToInt[value[i]];
}
That is,
AsciiToInt['2'] == 2
AsciiToint['T'] == 10,
AsciiToInt['J'] == 11
etc, but all invalid entries are zero.