How to parse strings properly in c - c

So I have this function :
char *lookUpPageTable(char **array, int VPN)
{
if (array[VPN][0] == '1')
{
/*char **pageNumber = (char **)malloc(sizeof(char*)* 128);
for (int i = 0; i < strlen(array); i++)
{
pageNumber[i] = array[VPN][i];
}*/
return array[VPN]; //this returns the whole number which I dont want
}
else
{
return "Page Fault";
}
}
The array I'm passing in as a parameter holds a list of numbers in the form 1 123456 where the first number is either a 1 or a 0 and the second number is a random number. This function checks the first number at index VPN in the array. If it is a zero, it should return a "Page Fault" string. If it is a 1, then the function should return the number after the 1.
For example, if i called lookUpPageTable(array, index)
The method should see if array[index][0] == '1'
If it does then return the remaining numbers at array[index]
else
return "page fault"

array[VPN] is the VPN-th element of the array, which happens to be a pointer to the string "1 123456" as you say. If you return array[VPN] + 1, for example, it would be a pointer to the string " 123456".
So you may return array[VPN] + 2, and you will obtain a pointer to the string "123456" as desired.
Note, however, that I am relying on your guarantee that the string's contents are indeed something of the form "1 123456", and I would recommend that your code should also verify that the string really is of that form.

Related

Assign an integer to a single element string array in C

I cannot figure out how to assign an integer value to an array of string in C, assuming this is possible of course! I would like to change some elements from a char ** into different values and then re-assign them to their initial position into the array.
Practically, I have two element, "Mon" and "Aug", which I would like to become "01" and "08"...
So I tried something but unsuccessfully:
char *time_array[7] = {"45", "55", "11", "Mon", "29", "Aug", "2022"};
uint32_t day2convert = 1;
uint32_t month2convert = 8;
*time_array[3] = &day2convert; // not even with a cast (char) which gave same results
*time_array[5] = &month2convert;
for (j = 0; j < 7; ++j)
printf("after conversion : %s\n", time_array[j]);
/*
Results for the two elements are different at each main call, as I'm randomly picking values present in different memory allocations (maybe). Es. don, hug; 4on 8ug, ton xug...
Moreover i tried also with strcpy function as:
strcpy(time_array[3], &day2convert); //also with a cast (char)(&day2convert)
but still I retrieve a void string.
So, gently, I'm asking if there could be a way to do what I want in principle, but also asking for some explanations about array of string. Because what I learnt is that a char ** is an array of pointer so it should be right to assign a value to it as *array[ii] = &var (??? in search of confirmation)
... how to assign an integer value to an array of string (?)
time_array[] is not an array of strings. It is an array of pointers to strings. This distinction is important as string lifetimes need careful consideration. Here, the strings pointed to by time_array[i] are not certainty modifiable.
char *time_array[7] = {"45", "55", "11", "Mon", "29", "Aug", "2022"};
We could change the pointer by re-assigning a compound literal. It is easy to form a an integer like string with single digit values like 1-7. Yet the lifetime of the compound literal only lasts to the end of the block of code.
int day_index = 1;
time_array[3] = (char[3]){ '0', '0' + day_index, '\0'}; // , '\0' optional as rest is zero filled
// good for a while
Or perhaps make time_array[] an array of strings and then re-assign the indexed string.
char time_array[7][5] = {"45", "55", "11", "Mon", "29", "Aug", "2022"};
int day_index = 1;
strcpy(time_array[3], (char[3]){ '0', '0' + day_index });
// or
snprintf(time_array[3], sizeof time_array[3], "%02d", day_index);
// good indefinitely
You will want to convert each of the 7 day names to a number.
I wrote this "hash function" for quickly getting back 1 to 7 for "Sun" to "Saturday" (it only needs the first two characters of the name, and is case insensitive).
It will return false positives, but allows you to test the string you have against only one possible day name. If the function returns 2, then the string can be checked as a variation of "Tu", "TUE" "Tuesday". You don't have to examine the other six day names as possibilities.
Return of 0 indicates it is not a weekday name.
// Convert a day name (or 3 letter abbrev.) to index (1-7, Sun=1). Beware false positives!
int wkdayOrd( char cp[] ) { return "65013427"[*cp/2 + ~cp[1] & 0x7] & 0x7; }
If you carefully replace 2 with 1, 3 with 2, 4 with 3, etc. in the quoted string, it will return Mon=1 and Sun=7 as you desire...
And for month names "Jan-December" (3 letters necessary) into 1 to 12. Again, this is a "hash function" and other words can/will result in "false positives" that must be confirmed against only one proper month name string.
int monthOrd( char cp[] ) { return "DIE#CB#LJF#HAG#K"[ cp[1]/4&7 ^ cp[2]*2 &0xF ] &0xF; }
Give it a play and let us know if it helps you get where you want to be.
EDIT:
Demonstrating functionality, here is an example that satisfies the OP question. The LUT values have been adjusted so that "Mon(day)" is day 1.
This does the conversion (trusting the source string) without invoking sprintf(). Here, printf() is used for 'diagnostic testing' only.
static int monthOrd( char cp[] ) { return "DIE#CB#LJF#HAG#K"[ cp[1]/4&7 ^ cp[2]*2 &0xF ] &0xF; }
static int wkdayOrd( char cp[] ) { return "54072316"[*cp/2 + ~cp[1] & 0x7] & 0x7; }
static char *toDigitStr( int val ) { // multiple execution overwrites result
static char buf[3];
buf[0] = (char)('0' + val/10);
buf[1] = (char)('0' + val%10);
buf[2] = '\0';
return buf;
}
int main() {
char *dayName = "Mon";
printf( "%s ==> %s\n", dayName, toDigitStr( wkdayOrd( dayName ) ) );
char *mthName = "Aug";
printf( "%s ==> %s\n", mthName, toDigitStr( monthOrd( mthName ) ) );
mthName = "DECEMBER";
printf( "%s ==> %s\n", mthName, toDigitStr( monthOrd( mthName ) ) );
return 0;
}
Output:
Mon ==> 01
Aug ==> 08
DECEMBER ==> 12

How do you assign strings to a string data type in C?

I am trying to make a rock,paper,scissors game using functions in C yet I cant seem to figure out how to assign the string to a char variable after I initialize it. So what the function does is that it generates a random number and compares that number to ether rock paper or scissors. yet I cant assign the the string to a variable which what I want the function to return after its called
int getConsoleChoice()
{
char consolePick;
int randNum;
srand(time(NULL));
randNum = rand() % 3;
if(randNum == 0)
{
char consolePick = "Rock";
}
if(randNum == 1)
{
char consolePick = "Paper";
}
if(randNum == 2)
{
char consolePick = "Scissors";
}
return consolePick;
}
Declare the variable and function return value as char *, which is the type of a string in C.
char *getConsoleChoice()
{
char *consolePick;
int randNum;
srand(time(NULL));
randNum = rand() % 3;
if(randNum == 0)
{
consolePick = "Rock";
}
else if(randNum == 1)
{
consolePick = "Paper";
}
else
{
consolePick = "Scissors";
}
return consolePick;
}
You could also simplify this using an array:
char *getConsoleChoice()
{
char *moves[] = {"Rock", "Paper", "Scissors"};
int randNum;
srand(time(NULL));
randNum = rand() % 3;
return moves[randNum];
}
char represents a single character. A string is a bunch of these stored together somewhere in memory, with a NUL terminating character so we can detect where that string finishes. So, when we have a memory location storing a bunch of values of some type, we use a pointer. It holds a memory address that "points" at the start. The type for a string is char*.
To illustrate, let's draw out some bytes in memory showing a string at some address, let's imagine we have a 32-bit computer and for argument's sake the string begins at the address 0xffa01000:
0 1 2 3 4 5 6 7
+---+---+---+---+---+---+---+---+
0xffa01000 | R | o | c | k | ~ | ? | ? | ? |
+---+---+---+---+---+---+---+---+
The above is what "Rock" looks like in memory. Each one of those cells is one byte holding a char value. Note that I've used ~ to represent the NUL byte and ? to represent memory we don't care about (because it's not part of the string).
If you want to store a value that points to that string, you use a pointer:
const char* rock = "Rock";
With our example from earlier, the pointer rock now holds the address 0xffa01000 and if we start reading information out of memory from there until we hit the NUL byte, then we will have read the string "Rock".
You can use a pointer like an array. From above, rock[0] will give you the character 'R', rock[1] will give 'o', and so on...
So there's some basics on what strings actually are in C. But back to your game.
With what you're trying to do, the goal is probably to use a value of 0, 1 or 2 to represent a weapon. Because it's just easier to work with. You can always turn that into a string when you need to. Here is an example of how you could do that:
const char* weaponName(int w)
{
static const char* names[] = {
"Rock",
"Paper",
"Scissors"
};
// Note: the defensive programming approach would also range-test this index
// before using it.
return names[w];
}
This function just uses the weapon number as an index to find a string in an array. Think back to earlier... What we have here is just an array of pointers to strings that live somewhere in memory. You don't need to care where.
Note that I've also used const. Don't worry too much about that, but what this does is prevents me from accidentally modifying those strings. Modifying string literals is not allowed, and so we store them as constants to make the compiler complain if we try to modify them.
As for static, well that's another topic but it basically means that one copy of this array will be always in memory, even after the function returns. So I don't need to be concerned about my strings somehow not existing after the function returns. They probably wouldn't disappear anyway, but this makes sure.
Anyway, back to how to use this, it's quite simple. Your random weapon roll becomes a one-line function, and getting the string representation is just a call to the function we made earlier.
Here's some code that will roll a weapon 10 times and print out what it got:
int randomWeapon()
{
return rand() % 3;
}
int main()
{
// Seed the random generator -- you should only do this once!
srand(time(0));
for (int i = 0; i < 10; ++i)
{
int weapon = randomWeapon();
printf("%s\n", weaponName(weapon));
}
}

C - Why is this string not being assigned to the variable?

I've been trying to understand why my string/char array loses the value assigned to it in the for loop as soon as the loop ends. The value for token2 is a user input that gets shunted into the "token2" variable earlier on in the code. I have several checks prior to this portion and token2 is populated as expected.
int dayInt2;
char dayToken2[3];
//For loop to parse out the month portion of second token.
for (int i = 3; i < 5; i++)
{
dayToken2[i] = token2[i];
printf("For loop parse: %c\n", token2[i]);
}
dayToken2[3] = '\0'; //Add null pointer to the last character space of the string array.
printf("dayToken2 value: %s\n", dayToken2); //Debugging to check the value in dayToken2.
dayInt2 = atoi(dayToken2); //converts day
printf("dayInt2 value: %s\n", dayInt2); //Debugging to check if the string conversion to int worked.
dayToken2[3] is outside the array. The indexes are from zero. So the maximum index is 2.
printf("dayInt2 value: %s\n", dayInt2); is wrong. You try to print the integer but you say the printf that it should expect the string. It has to be printf("dayInt2 value: %d\n", dayInt2);
dayToken2[i] = token2[i]; is also wrong as i changes from 3 to 4. It has to be dayToken2[i - 3] = token2[i];. You can use memcpy for that memcpy(dayToken2, token2 + 3, 2);
When defining your char array, you set the max indices as 3, so there is only dayToken[0], dayToken[1], dayToken[2]. In your for loop you set i from 3-5, try doing from 0-2.

Access and store value by index in a pointer

I've got an assignment where I have to sum whole numbers up to 100 digits.
They gave me this struct to represent big numbers (I think there are better ways to represent this, but I'm not allowed to modify it):
typedef struct {
char* string;
int lengthError;
} BigNumber;
Where string is the number itself and lengthError is the length of the number or an error that is a previously defined enum.
I've also have the implementation of the sum function
BigNumber *sum(BigNumber* num1, BigNumber* num2) {
BigNumber* result = malloc(sizeof(BigNumber));
int limit = getLength(num1->lengthError, num2->lengthError);
result->string = malloc(limit);
int digitResult;
int index = limit -1;
int carry = 0;
while(index != -1) {
int d1 = ((int)num1->string[index]) - ((int)'0');
int d2 = ((int)num2->string[index]) - ((int)'0');
digitResult = d1 + d2 + carry;
if (digitResult > 9) {
digitResult = digitResult - 10;
carry = 1;
} else {
carry = 0;
}
itoa(digitResult, &result->string[index], 10); //I think this is the problem
index--;
}
result->string[limit] = '\0';
printf("result: %s\n", result->string);
return result;
}
I haven't finished writing that function, I know there are a lot of flaws in it, but the problem is that I can't get to sum 12 + 12. The result I get is 2.
I thought approaching this problem by picking the lasts character of both numbers, transform them into an int and sum them having in mind the carry digit. After I got the result in digitResult I try to convert it to a char and store it in the corresponding position of the result->string pointer
Once it has finished the operation, I add an \0 at the last position of the result->string.
So the question is, how do I make this operation to work as desired? Debugging the code, I noticed that the first time it stores the first result in result->string, following the example above this would be a number 4, it stores trash in that position instead. In the second addition, I store a number 2 correctly and that's the final result I get in when I print the result.
Your use of the itoa function is a problem (though, as you have also suggested, maybe not the only one).
The itoa function converts its first argument into a null-terminated string - so, as well as writing the character representation of digitResult at the indicated place in the string, it also adds a '\0' character after it. Thus, your string will always be terminated immediately after the last digit you write, and 12 + 12, giving 24 will appear to be just the first character: 2.
What you can do instead is to convert the digit yourself (reversing the operation you used to get the d1 and d2 values), then just directly set the string element to the converted digit.
So, instead of:
itoa(digitResult, &result->string[index], 10);
use:
result->string[index] = (char)(digitResult + '0');

Trying to print form array or array addresses...not getting it?

new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.

Resources