Why does this C code give me a segmentation fault? - c

Using the CS50 library, this is my code but it keeps giving me a segmentation fault. I have tried to figure out where it keeps doing a segmentation fault, and for some reason it has to do with my function. Why does it keep doing this?
#import <cs50.h>
#import <stdio.h>
#import <ctype.h>
#import <string.h>
string ciphertext(string plaintext[1], string key[1]);
int main(int argc, string argv[])
{
// Variables
string plaintext2[1];
if (argc == 2)
{
if(strlen(argv[1]) == 26)
{
string text = get_string("plaintext: ");
plaintext2[0] = text;
}
else
{
printf("Key must contain 26 characters.\n");
return 1;
}
}
else
{
printf("Usage: ./substitution key\n");
return 1;
}
string ciphertext2 = ciphertext(&plaintext2[0], &argv[1]);
printf("ciphertext: %s\n", ciphertext2);
}
string ciphertext(string plaintext[1], string key[1])
{
// Variables
string ciphertext[1];
for (int i = 0; i < strlen(plaintext[0]); i++)
{
if (plaintext[0][i] == 'a')
{
ciphertext[0][i] = tolower(key[0][0]);
}
else if (plaintext[0][i] == 'A')
{
ciphertext[0][i] = toupper(key[0][0]);
}
else if (plaintext[0][i] == 'b')
{
ciphertext[0][i] = tolower(key[0][1]);
}
else if (plaintext[0][i] == 'B')
{
ciphertext[0][i] = toupper(key[0][1]);
}
else if (plaintext[0][i] == 'c')
{
ciphertext[0][i] = tolower(key[0][2]);
}
else if (plaintext[0][i] == 'C')
{
ciphertext[0][i] = toupper(key[0][2]);
}
else if (plaintext[0][i] == 'd')
{
ciphertext[0][i] = tolower(key[0][3]);
}
else if (plaintext[0][i] == 'D')
{
ciphertext[0][i] = toupper(key[0][3]);
}
else if (plaintext[0][i] == 'e')
{
ciphertext[0][i] = tolower(key[0][4]);
}
else if (plaintext[0][i] == 'E')
{
ciphertext[0][i] = toupper(key[0][4]);
}
else if (plaintext[0][i] == 'f')
{
ciphertext[0][i] = tolower(key[0][5]);
}
else if (plaintext[0][i] == 'F')
{
ciphertext[0][i] = toupper(key[0][5]);
}
else if (plaintext[0][i] == 'g')
{
ciphertext[0][i] = tolower(key[0][6]);
}
else if (plaintext[0][i] == 'G')
{
ciphertext[0][i] = toupper(key[0][6]);
}
else if (plaintext[0][i] == 'h')
{
ciphertext[0][i] = tolower(key[0][7]);
}
else if (plaintext[0][i] == 'H')
{
ciphertext[0][i] = toupper(key[0][7]);
}
else if (plaintext[0][i] == 'i')
{
ciphertext[0][i] = tolower(key[0][8]);
}
else if (plaintext[0][i] == 'I')
{
ciphertext[0][i] = toupper(key[0][8]);
}
else if (plaintext[0][i] == 'j')
{
ciphertext[0][i] = tolower(key[0][9]);
}
else if (plaintext[0][i] == 'J')
{
ciphertext[0][i] = toupper(key[0][9]);
}
else if (plaintext[0][i] == 'k')
{
ciphertext[0][i] = tolower(key[0][10]);
}
else if (plaintext[0][i] == 'K')
{
ciphertext[0][i] = toupper(key[0][10]);
}
else if (plaintext[0][i] == 'l')
{
ciphertext[0][i] = tolower(key[0][11]);
}
else if (plaintext[0][i] == 'L')
{
ciphertext[0][i] = toupper(key[0][11]);
}
else if (plaintext[0][i] == 'm')
{
ciphertext[0][i] = tolower(key[0][12]);
}
else if (plaintext[0][i] == 'M')
{
ciphertext[0][i] = toupper(key[0][12]);
}
else if (plaintext[0][i] == 'n')
{
ciphertext[0][i] = tolower(key[0][13]);
}
else if (plaintext[0][i] == 'N')
{
ciphertext[0][i] = toupper(key[0][13]);
}
else if (plaintext[0][i] == 'o')
{
ciphertext[0][i] = tolower(key[0][14]);
}
else if (plaintext[0][i] == 'O')
{
ciphertext[0][i] = toupper(key[0][14]);
}
else if (plaintext[0][i] == 'p')
{
ciphertext[0][i] = tolower(key[0][15]);
}
else if (plaintext[0][i] == 'P')
{
ciphertext[0][i] = toupper(key[0][15]);
}
else if (plaintext[0][i] == 'q')
{
ciphertext[0][i] = tolower(key[0][16]);
}
else if (plaintext[0][i] == 'Q')
{
ciphertext[0][i] = toupper(key[0][16]);
}
else if (plaintext[0][i] == 'r')
{
ciphertext[0][i] = tolower(key[0][17]);
}
else if (plaintext[0][i] == 'R')
{
ciphertext[0][i] = toupper(key[0][17]);
}
else if (plaintext[0][i] == 's')
{
ciphertext[0][i] = tolower(key[0][18]);
}
else if (plaintext[0][i] == 'S')
{
ciphertext[0][i] = toupper(key[0][18]);
}
else if (plaintext[0][i] == 't')
{
ciphertext[0][i] = tolower(key[0][19]);
}
else if (plaintext[0][i] == 'T')
{
ciphertext[0][i] = toupper(key[0][19]);
}
else if (plaintext[0][i] == 'u')
{
ciphertext[0][i] = tolower(key[0][20]);
}
else if (plaintext[0][i] == 'U')
{
ciphertext[0][i] = toupper(key[0][20]);
}
else if (plaintext[0][i] == 'v')
{
ciphertext[0][i] = tolower(key[0][21]);
}
else if (plaintext[0][i] == 'V')
{
ciphertext[0][i] = toupper(key[0][21]);
}
else if (plaintext[0][i] == 'w')
{
ciphertext[0][i] = tolower(key[0][22]);
}
else if (plaintext[0][i] == 'W')
{
ciphertext[0][i] = toupper(key[0][22]);
}
else if (plaintext[0][i] == 'x')
{
ciphertext[0][i] = tolower(key[0][23]);
}
else if (plaintext[0][i] == 'X')
{
ciphertext[0][i] = toupper(key[0][23]);
}
else if (plaintext[0][i] == 'y')
{
ciphertext[0][i] = tolower(key[0][24]);
}
else if (plaintext[0][i] == 'Y')
{
ciphertext[0][i] = toupper(key[0][24]);
}
else if (plaintext[0][i] == 'z')
{
ciphertext[0][i] = tolower(key[0][25]);
}
else if (plaintext[0][i] == 'Z')
{
ciphertext[0][i] = toupper(key[0][25]);
}
else
{
ciphertext[0][i] = plaintext[0][i];
}
}
return ciphertext[0];
}
I really need some help, and I don't know why it keeps giving a fault.

The array
string ciphertext[1];
is uninitialized and has indeterminate value.
Accessing such an array the way like this
ciphertext[0][i] = tolower(key[0][0]);
results in undefined behavior.
You need to allocate a character array with the size equal to the value of the expression
strlen( *plaintext ) + 1
Pay attention to that instead the numerous if-else statement you could define a string literal like for example
string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
and then you can use the standard string function strchr like
char *p = strchr( letters, toupper( ( unsigned char)plaintext[0][i] ) );
if ( p != NULL )
{
if ( plaintext[0][i] == *p )
{
ciphertext[0][i] = key[0][p - letters]);
}
else
{
ciphertext[0][i] = tolower(key[0][p - letters]);
}
}

You already have the answer (#Vlad from Moscow), but I would like to point out a few things:
Duplicating is a very bad practice, it is unreadable and more important seriously time-consuming. If you see "100" else if() statements one below the other you should suspect that something is terribly wrong with your code.
Try your best to avoid using numbers in your code. What if you want to change a value that you already copy-pasted a hundred times? Instead of using numbers, I would advise you to use variables and symbolic constants
Try to improve your current code, you can write something like this:
for (int i = 0; i < strlen(plaintext[0]); i++)
{
int ind = 0;
int lower_case = 97, upper_case = 65;
if (plaintext[0][i] == lower_case)
{
ciphertext[0][i] = tolower(key[0][ind]);
}
else if (plaintext[0][i] == upper_case)
{
ciphertext[0][i] = toupper(key[0][ind]);
}
ind++; lower_case++; upper_case++;
}

Related

Some Errors in my X and O game ( C language)

What I'm trying to do here is a tie toe game, but when my code enters the do - while part, it ends the process by itself. Since I could not solve this part, I did not have a chance to try whether there are other problems with the code, unfortunately, I would be glad if you could help with this issue.
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
char box_area[] = { '0','1','2','3','4','5','6','7','8','9' };
struct Player {
bool turn;
char mark;
int ID;
};
int main()
{
int return_result;
int player_number;
struct Player player1;
struct Player player2;
struct Player users[2];
users[0] = player1;
users[1] = player2;
(player1.mark = 'X') && (player2.mark = 'O');
(player1.turn = true) && (player2.turn = false);
(player1.ID = 1) && (player2.ID = 2);
do
{
box_creat();
for (int i = 0; i < 2; i++) {
if (users[i].turn == true)
{
make_move(users[i].ID);
box_creat();
users[i].turn = false;
users[i + 1].turn = true; \\ I made the logic of this section wrong
\\I will try to fix it, I realized after I sent the question
}
}
return_result = check_the_winner();
} while (return_result == 1 || return_result == -1);
return 0;
}
void box_creat(void) {
printf("| %c | %c | %c |", box_area[0], box_area[1], box_area[2]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[3], box_area[4], box_area[5]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[6], box_area[7], box_area[8]);
}
void make_move(int Player_ID)
{
int choice;
printf("Please select a area between 0-9 ");
scanf("%d", choice);
if (choice == '0' && box_area[0] == '0')
{
if (Player_ID == 1) {
box_area[0] = 'X';
}
else {
box_area[0] = 'O';
}
}
else if (choice == '1' && box_area[1] == '1')
{
if (Player_ID == 1) {
box_area[1] = 'X';
}
else {
box_area[1] = 'O';
}
}
else if (choice == '2' && box_area[2] == '2')
{
if (Player_ID == 1) {
box_area[2] = 'X';
}
else {
box_area[2] = 'O';
}
}
else if (choice == '3' && box_area[3] == '0')
{
if (Player_ID == 1) {
box_area[3] = 'X';
}
else {
box_area[3] = 'O';
}
}
else if (choice == '4' && box_area[4] == '0')
{
if (Player_ID == 1) {
box_area[4] = 'X';
}
else {
box_area[4] = 'O';
}
}
else if (choice == '5' && box_area[5] == '0')
{
if (Player_ID == 1) {
box_area[5] = 'X';
}
else {
box_area[5] = 'O';
}
}
else if (choice == '6' && box_area[6] == '0')
{
if (Player_ID == 1) {
box_area[6] = 'X';
}
else {
box_area[6] = 'O';
}
}
else if (choice == '7' && box_area[7] == '0')
{
if (Player_ID == 1) {
box_area[7] = 'X';
}
else {
box_area[7] = 'O';
}
}
else if (choice == '8' && box_area[8] == '0')
{
if (Player_ID == 1) {
box_area[8] = 'X';
}
else {
box_area[8] = 'O';
}
}
}
int check_the_winner(void)
{
if (box_area[0] && box_area[1] && box_area[2] == 'X' || 'O') {
return 1;
}
else if(box_area[3] && box_area[4] && box_area[5] == 'X' || 'O') {
return 1;
}
else if (box_area[6] && box_area[7] && box_area[8] == 'X' || 'O') {
return 1;
}
else if (box_area[2] && box_area[4] && box_area[6] == 'X' || 'O') {
return 1;
}
else if (box_area[0] && box_area[3] && box_area[6] == 'X' || 'O') {
return 1;
}
else if (box_area[2] && box_area[8] && box_area[5] == 'X' || 'O') {
return 1;
}
else if (box_area[0] && box_area[4] && box_area[8] == 'X' || 'O') {
return 1;
}
else if (box_area[1] && box_area[4] && box_area[7] == 'X' || 'O') {
return 1;
}
else {
return -1;
}
}
I tried out your program and found a few glitches that needed revision as well as adding in some additional bits of code just to neaten things up a bit. Following is your code with those revisions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
char box_area[] = { '0','1','2','3','4','5','6','7','8','9' };
struct Player
{
bool turn;
char mark;
int ID;
};
void box_creat(void)
{
printf("| %c | %c | %c |", box_area[0], box_area[1], box_area[2]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[3], box_area[4], box_area[5]);
printf("\n\n");
printf("| %c | %c | %c |", box_area[6], box_area[7], box_area[8]);
printf("\n"); /* Added for aesthetics */
}
void make_move(int Player_ID)
{
int choice;
printf("Player %d - please select a area between 0-9 ", Player_ID);
scanf("%d", &choice); /* Corrected missing ampersand */
printf("Player: %d makes a move\n", Player_ID);
if (choice == 0 && box_area[0] == '0') /* FYI - '0' is equivalent to integer value 48 */
{
if (Player_ID == 1)
{
box_area[0] = 'X';
}
else
{
box_area[0] = 'O';
}
}
else if (choice == 1 && box_area[1] == '1')
{
if (Player_ID == 1)
{
box_area[1] = 'X';
}
else
{
box_area[1] = 'O';
}
}
else if (choice == 2 && box_area[2] == '2')
{
if (Player_ID == 1)
{
box_area[2] = 'X';
}
else
{
box_area[2] = 'O';
}
}
else if (choice == 3 && box_area[3] == '3')
{
if (Player_ID == 1)
{
box_area[3] = 'X';
}
else
{
box_area[3] = 'O';
}
}
else if (choice == 4 && box_area[4] == '4')
{
if (Player_ID == 1)
{
box_area[4] = 'X';
}
else
{
box_area[4] = 'O';
}
}
else if (choice == 5 && box_area[5] == '5')
{
if (Player_ID == 1)
{
box_area[5] = 'X';
}
else
{
box_area[5] = 'O';
}
}
else if (choice == 6 && box_area[6] == '6')
{
if (Player_ID == 1)
{
box_area[6] = 'X';
}
else
{
box_area[6] = 'O';
}
}
else if (choice == 7 && box_area[7] == '7')
{
if (Player_ID == 1)
{
box_area[7] = 'X';
}
else
{
box_area[7] = 'O';
}
}
else if (choice == 8 && box_area[8] == '8')
{
if (Player_ID == 1)
{
box_area[8] = 'X';
}
else
{
box_area[8] = 'O';
}
}
}
int check_the_winner(void)
{
if ((box_area[0] == box_area[1]) && (box_area[1] == box_area[2]) && (box_area[0] != '0')) /* Corrected the testing for proper "and" conditioning */
{
return 1;
}
else if ((box_area[3] == box_area[4]) && (box_area[4] == box_area[5]) && (box_area[3] != '3'))
{
return 1;
}
else if ((box_area[6] == box_area[7]) && (box_area[7] == box_area[8]) && (box_area[6] != '6'))
{
return 1;
}
else if ((box_area[2] == box_area[4]) && (box_area[4] == box_area[6]) && (box_area[2] != '2'))
{
return 1;
}
else if ((box_area[0] == box_area[3]) && (box_area[3] == box_area[6]) && (box_area[0] != '0'))
{
return 1;
}
else if ((box_area[2] == box_area[5]) && (box_area[5] == box_area[8]) && (box_area[2] != '2'))
{
return 1;
}
else if ((box_area[0] == box_area[4]) && (box_area[4] == box_area[8]) && (box_area[4] != '4'))
{
return 1;
}
else if ((box_area[1] == box_area[4]) && (box_area[4] == box_area[7]) && (box_area[1] != '1'))
{
return 1;
}
else
{
return -1;
}
}
int main()
{
int return_result;
//int player_number; /* Compiler said that this wasn't being used */
int swap = 1;
int i;
struct Player player1;
struct Player player2;
struct Player *users[2]; /* Used these as address pointers to player "1" and player "2" */
users[0] = &player1; /* Before making these pointers, the users array just contained copies of the player structures */
users[1] = &player2;
(player1.mark = 'X') && (player2.mark = 'O');
(player1.turn = true) && (player2.turn = false);
(player1.ID = 1) && (player2.ID = 2);
do
{
box_creat();
swap += 1;
i = swap % 2;
if (i == 1)
{
make_move(users[1]->ID);
//box_creat(); /* Being performed at the top of the loop */
users[0]->turn = false;
users[1]->turn = true;
}
else
{
make_move(users[0]->ID);
//box_creat();
users[1]->turn = false;
users[0]->turn = true;
}
return_result = check_the_winner();
if (check_the_winner() == 1) /* Added when a winner has been sensed */
{
box_creat();
if (i == 1)
{
printf("Player 2 won!\n");
}
else
{
printf("Player 1 won!\n");
}
}
}
while (return_result != 1);
return 0;
}
I added comments to most of the places I had tweaked, but here are the highlights:
I shuffled some of the functions around so that the "main" function followed all of the helper functions (the compiler was giving warnings about the original sequence of the function positions).
I corrected the "choice" tests as "choice" is an integer, so the test of "choice" needed to be compared to an integer value (e.g. zero) as opposed to character '0' (which actually has a value of 48).
The tests for three letters in a row for either player do not work in that manner. Either a test needed to be made for each box for a certain row needed to tested for an "X" or an "O", and then if that test was true the test needed to be continued for the next box in the row, and then again for the third box in the row. In lieu of that route, the test was revised to basically say "if the character in the first box in the row is the same as the character in the second box in the row, and the character in the second box in the row is the same as the character in the third box in the row, and the first box does not contain a digit character (which means is contains an "X" or an "O"), then there is a winner.
It appears that an attempt was made to mirror the contents of "Player1" and "Player2" into an array of player structures. Although initially, structure "users[0]" contained the same data as "Player1" and structure "users[1]" contained the same data as "Player2", once the data in "Player1" and "Player2" were updated, those changes did to propagate over to the "users" array. So to utilize "users" in the spirit of this program, they were defined as pointers to their respective player structures.
Those were the most significant bits. The other bits were added for a logical conclusion of the game. Note that no logic was added for a draw.
Give that a test and see if that clarifies things and follows the spirit of the project.

My If-statements seem to be ignored even though my variables look fine in the debugger

I just started learning C (I'm an absolute beginner) and I'm trying to make a program that translates Roman numbers to Arabic and vice versa.
If I were to type "IX" my program should give me a "9" as an output but instead I get a "1". I tried to find the issue on my own using the debugger and I can see my program entering the first If-Statement
if (userString[localIndex] == 'I')
but then it skips the inner If-Statement
else if (userString[++localIndex] == 'X') {
ARABIC_NUM += 9;
localIndex++;
}
I'm not sure why this is happening. If I type "IV" my program outputs a "4" which is the correct answer but if I type "IVIV" my programs once again outputs a lonely "4" and ignores the rest of my input.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#define NOT_A_NUMBER 0
#define IS_ROMAN 1
#define IS_ARABIC 2
int ARABIC_NUM = 0;
int findStringLength(char* userString) {
int stringLength = 0;
size_t index = 0;
while (userString[index] != '\0')
{
if (userString[index] != '\0') {
stringLength++;
index++;
}
}
return stringLength;
}
void resetString(char* userString)
{
size_t stringLength = findStringLength(userString);
for (size_t index = 0; index < stringLength; index++)
{
userString[index] = '\0';
}
}
void printString(char* userString)
{
size_t stringLength = findStringLength(userString);
for (size_t index = 0; index < stringLength; index++)
{
if (userString[index] != '\0')
printf("~%zu:%c~ ", index, userString[index]);
else
printf("Null character");
}
}
bool ifEnd(char* numberInput, size_t counter) {
bool userEnd = false;
for (size_t index = 0; index < counter; index++)
{
if ((numberInput[index - 2] == 'E' && numberInput[index - 1] == 'N' && numberInput[index] == 'D')) {
userEnd = true;
}
}
return userEnd;
}
int isNumTrue(char userChar) {
int isRoman = NOT_A_NUMBER;
int isArabic = NOT_A_NUMBER;
if (userChar == 'I' || userChar == 'V' || userChar == 'X' ||
userChar == 'L' || userChar == 'C' || userChar == 'D' || userChar == 'M') {
isRoman = IS_ROMAN;
return isRoman;
}
else if (userChar == '0' || userChar == '1' || userChar == '2' || userChar == '3' || userChar == '4' || userChar == '5' || userChar == '6' || userChar == '7' || userChar == '8' || userChar == '9') {
isArabic = IS_ARABIC;
return isArabic;
}
else {
return NOT_A_NUMBER;
}
}
void convertToArabic(char* userString, size_t counter) {
for (size_t localIndex = 0; userString[localIndex] != '\0'; localIndex++) {
// printf("[ %c%s]", userString[localIndex], "-o ");
if (userString[localIndex] == 'I') {
if (userString[++localIndex] == 'V') {
printf("Made it in");
ARABIC_NUM += 4;
localIndex++;
}
else if (userString[++localIndex] == 'X') {
ARABIC_NUM += 9;
localIndex++;
}
else {
ARABIC_NUM += 1;
}
}
else if (userString[localIndex] == 'V') {
ARABIC_NUM += 5;
}
else if (userString[localIndex] == 'X') {
if (userString[localIndex++] == 'L') {
ARABIC_NUM += 40;
localIndex++;
}
else if (userString[localIndex++] == 'C') {
ARABIC_NUM += 90;
localIndex++;
}
else {
ARABIC_NUM += 10;
}
}
else if (userString[localIndex] == 'L') {
ARABIC_NUM += 50;
}
else if (userString[localIndex] == 'C') {
if (userString[localIndex++] == 'D') {
ARABIC_NUM += 400;
localIndex++;
}
else if (userString[localIndex++] == 'M') {
ARABIC_NUM += 900;
localIndex++;
}
else {
ARABIC_NUM += 100;
}
}
else if (userString[localIndex] == 'D') {
ARABIC_NUM += 500;
}
else if (userString[localIndex] == 'M') {
ARABIC_NUM += 1000;
}
else {
printf("Switch default. You shouldn't be seeing this");
}
/* else
{
printf("[ %c%s]", userString[localIndex],"-x ");
}*/
}
printf("%s%d%s", "\n Number was :", ARABIC_NUM, "\n");
}
bool convertToRoman(char* userString, char* romanStringHolder, size_t counter) {
bool isValid = true;
int arabicNum = atoi(userString);
char repetitionLimit = '\0';
for (size_t index = 0; arabicNum != 0; index++) {
/* if ((isNumTrue(userString[index]) == IS_ARABIC || userString[index] == '\n') && index < counter)
{
printf("[ %c%s]", userString[index], "-o ");
}*/
if (arabicNum >= 4000) {
do {
if (romanStringHolder[index - 2] == romanStringHolder[index - 1] == romanStringHolder[index]) {
repetitionLimit = romanStringHolder[index - 2];
}
if (arabicNum / 1000000 >= 1)//&& repetitionLimit != 'M')
{
romanStringHolder[index] = 'M';
arabicNum -= 1000000;
}
else if (arabicNum / 900000 >= 1)// && repetitionLimit != 'M')
{
romanStringHolder[index] = 'C';
romanStringHolder[++index] = 'M';
arabicNum -= 900000;
}
else if (arabicNum / 500000 >= 1)// && repetitionLimit != 'D')
{
romanStringHolder[index] = 'D';
arabicNum -= 500000;
}
else if (arabicNum / 400000 >= 1)//&& repetitionLimit != 'D')
{
romanStringHolder[index] = 'C';
romanStringHolder[++index] = 'D';
arabicNum -= 400000;
}
else if (arabicNum / 100000 >= 1)// && repetitionLimit != 'C')
{
romanStringHolder[index] = 'C';
arabicNum -= 100000;
}
else if (arabicNum / 90000 >= 1)//&& repetitionLimit != 'C')
{
romanStringHolder[index] = 'X';
romanStringHolder[++index] = 'C';
arabicNum -= 90000;
}
else if (arabicNum / 50000 >= 1)// && repetitionLimit != 'L')
{
romanStringHolder[index] = 'L';
arabicNum -= 50000;
}
else if (arabicNum / 40000 >= 1)// && repetitionLimit != 'L')
{
romanStringHolder[index] = 'X';
romanStringHolder[++index] = 'L';
arabicNum -= 40000;
}
else if (arabicNum / 10000 >= 1)//&& repetitionLimit != 'X')
{
romanStringHolder[index] = 'X';
arabicNum -= 10000;
}
else if (arabicNum / 9000 >= 1)// && repetitionLimit != 'X')
{
romanStringHolder[index] = 'I';
romanStringHolder[++index] = 'X';
arabicNum -= 9000;
}
else if (arabicNum / 5000 >= 1)//&& repetitionLimit != 'V')
{
romanStringHolder[index] = 'V';
arabicNum -= 5000;
}
else if (arabicNum / 4000 >= 1)//&& repetitionLimit != 'I')
{
romanStringHolder[index] = 'I';
romanStringHolder[++index] = 'V';
arabicNum -= 4000;
}
else if (arabicNum / 1000 >= 1)// && repetitionLimit != 'I')
{
romanStringHolder[index] = 'I';
arabicNum -= 1000;
}
index++;
} while (arabicNum >= 4000);
romanStringHolder[index] = '_';
index++;
}
if (arabicNum <= 3999) {
if (arabicNum / 1000 >= 1)
{
romanStringHolder[index] = 'M';
arabicNum -= 1000;
}
if (arabicNum / 900 >= 1)
{
romanStringHolder[index] = 'C';
romanStringHolder[++index] = 'M';
arabicNum -= 900;
}
else if (arabicNum / 500 >= 1)
{
romanStringHolder[index] = 'D';
arabicNum -= 500;
}
else if (arabicNum / 400 >= 1)
{
romanStringHolder[index] = 'C';
romanStringHolder[++index] = 'D';
arabicNum -= 400;
}
else if (arabicNum / 100 >= 1)
{
romanStringHolder[index] = 'C';
arabicNum -= 100;
}
else if (arabicNum / 90 >= 1)
{
romanStringHolder[index] = 'X';
romanStringHolder[++index] = 'C';
arabicNum -= 90;
}
else if (arabicNum / 50 >= 1)
{
romanStringHolder[index] = 'L';
arabicNum -= 50;
}
else if (arabicNum / 40 >= 1)
{
romanStringHolder[index] = 'X';
romanStringHolder[++index] = 'L';
arabicNum -= 40;
}
else if (arabicNum / 10 >= 1)
{
romanStringHolder[index] = 'X';
arabicNum -= 10;
}
else if (arabicNum / 9 >= 1)
{
romanStringHolder[index] = 'I';
romanStringHolder[++index] = 'X';
arabicNum -= 9;
}
else if (arabicNum / 5 >= 1)
{
romanStringHolder[index] = 'V';
arabicNum -= 5;
}
else if (arabicNum / 4 >= 1)
{
romanStringHolder[index] = 'I';
romanStringHolder[++index] = 'V';
arabicNum -= 4;
}
else if (arabicNum / 1 >= 1)
{
romanStringHolder[index] = 'I';
arabicNum -= 1;
}
}
}
if (romanStringHolder > 3999999)
printf("\n");
return isValid;
}
int findNumSystem(char* userString, char* toRomanString) {
//printf(" -%zu and %d-", counter, findStringLength(userString));
size_t counter = findStringLength(userString);
int romanNumAmount = 0;
int arabicNumAmount = 0;
int notNumAmount = 0;
for (size_t localIndex = 0; localIndex < counter; localIndex++) {
if (isNumTrue(userString[localIndex]) == IS_ROMAN || ((isNumTrue(userString[localIndex - 1]) == IS_ROMAN) && (userString[localIndex] == '\n')))
{
printf("[ %c%s]", userString[localIndex], "-R ");
romanNumAmount++;
if (romanNumAmount == (findStringLength(userString) - 1)) {
printf("\nAll Numbers are Roman");
convertToArabic(userString, counter);
break;
}
}
else if (isNumTrue(userString[localIndex]) == IS_ARABIC || ((isNumTrue(userString[localIndex - 1]) == IS_ARABIC) && (userString[localIndex] == '\n')))
{
printf("[ %c%s]", userString[localIndex], "-A ");
arabicNumAmount++;
if (arabicNumAmount == (findStringLength(userString) - 1))
{
printf("\nAll numbers are Arabic");
convertToRoman(userString, toRomanString, counter);
printString(toRomanString);
break;
}
}
else if (isNumTrue(userString[localIndex]) == NOT_A_NUMBER)
{
printf("[ %c%s]", userString[localIndex], "-X ");
notNumAmount++;
if (notNumAmount == (findStringLength(userString))) {
printf("\nNone of the characters is a number of either system");
}
}
}
}
#define LENGTH 1000u
int main() {
typedef char user_Input_Stream;
char lol = '\0';
user_Input_Stream arabToRomanString[LENGTH] = { '\0' };
user_Input_Stream numberInput[LENGTH] = { '\0' };
size_t counter = 0;
bool userEnd = false;
while ((lol != EOF) && (userEnd == false))
{
counter = 0;
printString(&numberInput);
resetString(&numberInput);
resetString(&arabToRomanString);
counter = 0;
printString(&numberInput);
ARABIC_NUM = 0;
printf("\n\n||Beta version, remember to not mix number systems yet||\n");
//Repeats until variable lol countains EOF or until boolean holds a true value
while ((lol != EOF) && (lol != '\n') && (userEnd == false))
{
//gets characters, assigns string with them. Gets rid of newline and stores string in array in uppercase
lol = getchar();
numberInput[counter] = toupper(lol);
userEnd = ifEnd(numberInput, counter);
counter++;
}
//TESTING Travels through String and outputs cells contents. Also, sets boolean to True if user writes END
for (size_t i = 0; i < counter; i++) {
if (numberInput[i] == '\n')
{
lol = '\\';
numberInput[i] = toupper(lol);
}
// printf("| [%zu] = %c |", i, numberInput[i]);
}
findNumSystem(numberInput, arabToRomanString);
printf("\n");
}
printf("\n");
return 0;
}
Does anyone have an idea of what the issue could be? (ARABIC_NUM is a global variable, the name is to make it easier for me to find for now.)
Just in case this might help somebody else, here's the solution I came up with using some of the pointers people in the comment section gave me. It was fairly simple:
I was under the impression that expressions within if-statements don't affect any variables they reference, but in reality they do.
For example: if(userString[localIndex] == 'I' && userString[localIndex++] == 'X')
In the line above, I was expecting the program to check both the current index and the next upcoming index, which it did but the expression userString[localIndex++] within the if-statement also permanently incremented my localIndex variable when I wasn't expecting that change to exist outside of the if-statement's parenthesis. So, my program would check the wrong indexes after the first comparison was made and thus why it gave me the wrong output.
To solve this, I created the variable nextIndex and used it to store the value localIndex +1 meaning it will always represent the index after localIndex. So, It now works as intended.
Below is what my program looks like now. (I moved around the if and if-else statements for better readability but the only changed that solved my predicament was the addition of nextIndex)
void convertToArabic(char* userString, size_t counter) {
size_t nextIndex = 0;
for (size_t localIndex = 0; localIndex < findStringLength(userString); localIndex++) {
// printf("[ %c%s]", userString[localIndex], "-o ");
nextIndex = localIndex+1;
if (userString[localIndex] == 'M') {
ARABIC_NUM += 1000;
}
else if (userString[localIndex] == 'C' && userString[nextIndex] == 'M') {
ARABIC_NUM += 900;
localIndex++;
}
else if (userString[localIndex] == 'D') {
ARABIC_NUM += 500;
}
else if (userString[localIndex] == 'C' && userString[nextIndex] == 'D') {
ARABIC_NUM += 400;
localIndex++;
}
else if(userString[localIndex] == 'C'){
ARABIC_NUM += 100;
}
else if (userString[localIndex] == 'X' && userString[nextIndex] == 'C') {
ARABIC_NUM += 90;
localIndex++;
}
else if (userString[localIndex] == 'L') {
ARABIC_NUM += 50;
}
else if (userString[localIndex] == 'X' && userString[nextIndex] == 'L'){
ARABIC_NUM += 40;
localIndex++;
}
else if (userString[localIndex] == 'X') {
ARABIC_NUM += 10;
}
else if ((userString[localIndex] == 'I') && (userString[nextIndex] == 'X')) {
//localIndex--;
ARABIC_NUM += 9;
localIndex++;
}
else if (userString[localIndex] == 'V') {
ARABIC_NUM += 5;
}
else if ((userString[localIndex] == 'I') && (userString[nextIndex] == 'V')) {
//localIndex--;
printf("Made it in");
ARABIC_NUM += 4;
localIndex++;
}
else if (userString[localIndex] == 'I') {
ARABIC_NUM += 1;
}
/* else
{
printf("[ %c%s]", userString[localIndex],"-x ");
}*/
}
printf("%s%d%s", "\n Number was :", ARABIC_NUM, "\n");
}

bin node search in map

I try to search in a map I created. Each cell have 3 branches. When A is the closest, B after and C is the farthest. I'm trying to find the shortest route.
It is possible, for instance, that b->c->c->a is closer than a->a->a->a->a.
What should I do?
gag *pathfinder(gag *root, int choice)
{
if (root == NULL)
{
printf_s("the map didnt exits.");
getchar();
exit(1);
}
if (choice == root->index)
{
printf_s("(%d,%d)", root->x, root->y);
return root;
}
if (choice != root->index)
if (root->A != NULL)
{
if (root->A->index != NULL && root->A->index == choice)
;
else
{
pathfinder(root->A, choice);
}
}
else if (choice != root->index)
if (root->B != NULL)
{
if (root->B->index != NULL && root->B->index == choice)
; // printf_s("(%d,%d)->", root->B->x, root->B->y);
else
{
pathfinder(root->B, choice);
}
}
else if (choice != root->index)
if (root->C != NULL)
{
if (root->C->index != NULL && root->C->index == choice)
; //
printf_s("(%d,%d)->", root->C->x, root->C->y);
else
{
pathfinder(root->C, choice);
printf_s("(%d,%d)->", root->C->x, root->C->y);
}
}
}
gag* path(gag *map, gag* tree, int len) {
char temp = map->index;
gag* hold;
tree->index = temp;
static int c = -1;
int *close;
c++;
(map)->index = 'v'; // Mark as visited.
(map)->entries++;
//go A
if (!map->A || map->A->index == 'v' || map->A->entries == 3)
tree->A = NULL;
else {
hold = malloc(sizeof(gag)*len);
d_p_s(map, hold);
tree->A = path(map->A, hold, len);
}
//go B
if (!map->B || map->B->index == 'v' || map->B->entries == 3)
tree->B = NULL;
else {
hold = malloc(sizeof(gag)*len);
d_p_s(map, hold);
tree->B = path(map->B, hold, len);
}
//go C
if (!map->C || map->C->index == 'v' || map->C->entries == 3)
tree->C = NULL;
else {
hold = malloc(sizeof(gag*)*len);
d_p_s(map, hold);
tree->C = path(map->C, hold, len);
}
map->index = temp;
return tree;
}

C programming, only the first if statement works

I was wondering if anyone could help me understand why only my first if statements is working. Basically, I am working on a l33t speak convertor (lol) and only my first if statement works, here is my code:
#include<stdio.h>
#include<string.h>
void translate (char blurp[]);
int main(void) {
char message[1024];
printf("enter a message: \n");
fgets(message, 1024, stdin);
translate(message);
return 0;
}
void translate (char blurp[]) {
int i;
int length;
length = strlen(blurp);
printf("\nHere it is translated: \n");
for ( i = 0; i != length; i++) {
if (blurp[i] == 'a') {
blurp[i] = '4';
printf("%c", blurp[i]);
}
else if (blurp[i] == 'b') {
blurp[i] = '8';
printf("%c", blurp[i]);
}
else if (blurp[i] == 'e') {
blurp[i] = '3';
printf("%c", blurp[i]);
}
else if (blurp[i] == 'i') {
blurp[i] = '|';
printf("%c", blurp[i]);
}
else if (blurp[i] == 'o') {
blurp[i] = '0';
printf("%c", blurp[i]);
}
else if (blurp[i] == 's') {
blurp[i] = '5';
printf("%c", blurp[i]);
}
else {
printf("%c", blurp[i]);
}
}
}

Errors in my Tic-Tac-Toe Game

Here's my code for my tic-tac-toe game:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int board[3][3] = {
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}
};
int main (void)
{
int const user1 = 1;
int const user2 = 2;
char move[10];
while (! all_locations_filled()) {
printf("User-1, please enter your move:");
scanf("%s", move);
if(valid_location(move)) {
mark_location(user1, move);
display_board(board[3][3]);
}
else if(won_the_game(user1)) {
printf("Congratulations User-1, You Won the Game!");
break;
}
else {
printf("Invalid Move");
}
printf("User-2, please enter your move:");
scanf("%s", move);
if(valid_location(move)) {
mark_location(user2, move);
display_board();
}
else if(won_the_game(user2) {
printf("Congratulations User-2, You Won the Game!");
break;
}
else {
printf("Invalid Move");
}
}
return 0;
}
bool valid_location(char str[10]) {
int strcmp(x, y);
if (strcmp(str[10], "upperLeft") == 0 || strcmp(str[10], "up") == 0 || strcmp(str[10], "upperRight") == 0 || strcmp(str[10], "left") == 0 || strcmp(str[10], "center") == 0 || strcmp(str[10], "right") == 0 || strcmp(str[10], "lowerLeft") == 0 || strcmp(str[10], "down") == 0 || strcmp(str[10], "lowerRight") == 0)
return true;
}
void mark_location(int userU, char str[10]) {
int strcmp(x, y);
if (strcmp(str[10], "upperLeft") == 0)
board[0][0] = userU;
else if (strcmp(str[10], "up") == 0)
board[0][1] = userU;
else if (strcmp(str[10], "upperRight") == 0)
board[0][2] = userU;
else if (strcmp(str[10], "left") == 0)
board[1][0] = userU;
else if (strcmp(str[10], "center") == 0)
board[1][1] = userU;
else if (strcmp(str[10], "right") == 0)
board[1][2] = userU;
else if (strcmp(str[10], "lowerLeft") == 0)
board[2][0] = userU;
else if (strcmp(str[10], "down") == 0)
board[2][1] = userU;
else if (strcmp(str[10], "lowerRight") == 0)
board [2][2] = userU;
}
char display_board(int array[][]) {
int i, j;
for (i=0; i<3; ++i)
for (j=0; j<3; ++j)
if (array[i][j] == 0)
print("-");
else if (array[i][j] == 1)
print("x");
else if (array[i][j] == 2)
print("o");
}
bool all_locations_filled() {
int i, j;
for (i=0; i<3; ++i)
for (j=0; j<3; ++j)
if board[i][j] == 0
return false;
return true;
}
bool won_the_game(userU) {
int i, j;
if (board[0][0] == userU && board[0][1] == userU && board[0][2] == userU)
return true;
else if (board[1][0] == userU && board[1][1] == userU && board[1][2] == userU)
return true;
else if (board[2][0] == userU && board[2][1] == userU && board[2][2] == userU)
return true;
else if (board[0][0] == userU && board[1][0] == userU && board[2][0] == userU)
return true;
else if (board[0][1] == userU && board[1][1] == userU && board[2][1] == userU)
return true;
else if (board[0][2] == userU && board[1][2] == userU && board[2][2] == userU)
return true;
else if (board[0][0] == userU && board[1][1] == userU && board[2][2] == userU)
return true;
else if (board[2][2] == userU && board[1][1] == userU && board[2][0] == userU)
return true;
else
return false;
}
There are a few errors that I don't understand, here they are:
tictactoe.c:50: error: expected expression before ‘}’ token
This error is at the end of the main function but I'm not sure what I did wrong.
tictactoe.c:52: error: nested functions are disabled, use -fnested-functions to re-enable
I didn't know I used a nested function.
tictactoe.c:53: warning: parameter names (without types) in function declaration
This is referring to int strcmp(x, y)
tictactoe.c:55: warning: passing argument 1 of ‘strcmp’ makes pointer from integer without a cast
What did I do wrong with strcmp?
If someone could help me out I'd greatly appreciate it.
You're missing a closing parenthesis here (line #40):
else if(won_the_game(user2) {
Should be:
else if(won_the_game(user2)) {
You have a couple or problems with the strcmp as well.
strcmp(str[10], "upperRight")
The compiler is complaining about the first parameter str[10]. One problem is that this selects a single character from the string, and not the whole string. Another problem is that in an array of size 10, the positions are numbered 0..9 so there isn't even a position 10!
Also, a string literal like "upperRight" contains 10 visible characters plus an extra zero character as a terminator. So it needs 11 positions when stored in the str.

Resources