eof(f) in file handling in c programing - c

i have just built a program that reads a data from a file named "text.txt" and parse it through JSON as i know the size of a file that im reading character wise so in for loop i have defined the value of i in for loop as 647, pleas help me if the value increases or decreases then how would i manage it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "jsmn.h"
void error(char *msg)
{
perror(msg);
exit(0);
}
static int jsoneq(const char *json, jsmntok_t *tok, const char *s)
{
if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && strncmp(json + tok->start, s, tok->end - tok->start) == 0)
{
return 0;
}
return -1;
}
int main(int argc, char const *argv[])
{
int i,n,r;
char buf[1024];
char JSON_STRING[5000];
jsmn_parser p;
jsmntok_t t[2048];
char * fname;
FILE *fp=fopen("text.txt","r+");
FILE *ff;
if(fp==NULL)
{
error("file opening error");
}
for(int i=0; i<647;i++) /////////this if the for loop //////////
{
JSON_STRING[i] = getc(fp);
}
jsmn_init(&p);
r = jsmn_parse(&p,JSON_STRING, strlen(JSON_STRING), t, sizeof(t)/sizeof(t[0]));
if (r < 0){
printf("\nFailed to parse JSON: %d\n", r);
return 1;
}
else{
for (i = 1; i < r; i++){
if (jsoneq(JSON_STRING, &t[i], "RID") == 0)
// for extracting the value of Rid from the complete string
{/* We may use strndup() to fetch string value */
//printf("RID: '%.*s'\n",t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start);
printf("- RID: %.*s\n", t[i+1].end-t[i+1].start,JSON_STRING + t[i+1].start);
sprintf(fname,"%.*s",t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start);
ff=fopen (fname, "w");
fprintf(ff, "RID: '%.*s'\n",t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start );
i++;
}
}
else if (jsoneq(JSON_STRING, &t[i], "DID") == 0) //for Extracting the value of DID from te string recived from the client JSON_STrING
{
/* We may additionally check if the value is either "true" or "false"*/
printf("- DID: %.*s\n", t[i+1].end-t[i+1].start,JSON_STRING + t[i+1].start);
fprintf(ff, "DID: '%.*s'\n",t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start );
i++;
//sprintf(fname,"%s_%.*s",fname,t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start);
}
else if (jsoneq(JSON_STRING, &t[i],"TS") == 0)
{
/* We may want to do strtol() here to get numeric value */
printf("- TS: %.*s\n", t[i+1].end-t[i+1].start,JSON_STRING + t[i+1].start);
fprintf(ff, "TS: '%.*s'\n",t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start );
// sprintf(fname,"%s_%.*s",fname,t[i+1].end - t[i+1].start, JSON_STRING+ t[i+1].start);
}
/* else
{
printf("Unexpected key: %.*s\n", t[i].end-t[i].start,JSON_STRING + t[i].start);}*/
}
printf("JSON parsed : %d\n", r);
printf("output have been generated to the file");
fprintf(ff, "%s\n",JSON_STRING );
fclose(ff);
}
return EXIT_SUCCESS;
fclose(fp);
return 0;
}

You need first to compute the amount of characters in the file, which will be the size of your json buffer
//computing how much data is needed
fseek(fp, 0L, SEEK_END);
long int json_size = ftell(fp);
rewind(fp);
Then read the file till you reach the end of the buffer or till the value read is EOF. With the code above both these conditions are the same, but under other conditions you must use both tests. Which give
JSON_STRING = (char*)malloc(json_size+1 * sizeof(char));
JSON_STRING[json_size] = '\0';
//reading the value
int val = 0;
int i = 0;
while(i < json_size && (val = getc(fp)) != EOF)
{
JSON_STRING[i] = val;
++i;
}

Related

How do I correctly read a file byte by byte without losing any information [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I guess the real goal is to successfully mimic strace's output in regards to the read() syscall argument reading that it magically outputs.
And to make this as clear as possible:
It means that it displays them in a way that WILL NOT be interpreted by the console. For example, if a file contains \0004 or \0104 then it will DISPLAY \0004 and \0104 as LITERAL STRINGS (as if you wrote \\0004 or \\0104 instead) so it will NOT be interpreted by the console.
#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char * argv[]) {
#include <stdio.h>
int shift(int times) {
#ifdef SHIFT_VERBOSE
int shift_mode_verbose = 1;
#else
int shift_mode_verbose = 0;
#endif
if (shift_mode_verbose == 1) {
printf("The following arguments were passed (before) to main(%i):\n", argc);
for(int i=1; i<argc; i++) {
printf("arg%i: %s\n", i, argv[i]);
}
printf("\n");
}
if (shift_mode_verbose == 1) {printf("shifting %i times\n", times);}
for(int t=1; t<times+1; ++t) { // we set this to 1 and respectively increase by 1, to avoid shifting argv[0] as it is holds the program name
for(int i=1; i<argc; ++i) { // we set this to 1 to avoid shifting argv[0] as it is holds the program name
if (shift_mode_verbose == 1) {printf("shift %i: arg%i: %s >", t, i, argv[i]);}
argv[i] = argv[i+1];
if (shift_mode_verbose == 1) {printf(" %s\n", argv[i]);}
}
--argc;
}
if (shift_mode_verbose == 1) {
printf("The following arguments were passed (after) to main(%i):\n", argc);
for(int i=1; i<argc; i++) {
printf("arg%i: %s\n", i, argv[i]);
}
printf("\n");
}
return 0;
}
int fshift(int times) { // a potentially faster version of shift()
times = argc < times ? argc : times;
argc = (argc) - times;
(argv) += times;
return 0;
}
if (argc < 3) {
printf("Usage: %s lines (-1 = all lines), files\n", argv[0]);
return 1;
}
int LINES_TO_READ = atoi(argv[1]);
shift(1);
for (ssize_t i = 1; i < argc; i++) {
const char *filename = argv[i];
printf("printing \"%s\"\n\n", filename);
int fd = open(filename, O_RDONLY);
if (fd < 0) {
printf("cannot open \"%s\", returned %i\n", filename, fd);
return -1;
}
char unsigned ch;
size_t lines = 1;
// Read the file byte by byte
while (read(fd, &ch, 1) == 1) {
if (ch == '\n') {
printf("\\n");
} else if (ch == '\0') {
printf("\\0");
} else if (ch == '\r') {
printf("\\r");
} else if (ch == '\t') {
printf("\\t");
} else if(isprint(ch)) {
printf("%c", ch);
} else {
printf("\\%03o", ch);
}
// FILE *file = fopen(filename, "rb");
// char unsigned ch;
// size_t lines = 1, bytes=1;
// // Read the file byte by byte
// while (fread(&ch, 1, 1, file) == 1) {
// if (ch == '\n') {
// printf("\\n");
// } else if (ch == '\0') {
// printf("\\0");
// } else if (ch == '\r') {
// printf("\\r");
// } else if (ch == '\t') {
// printf("\\t");
// } else if(isprint(ch)) {
// printf("%c", ch);
// } else {
// printf("\\%03o", ch);
// }
if (ch == '\n') {
// Stop if we read 10 lines already
if (lines == LINES_TO_READ) {
break;
}
lines++;
}
}
if (close(fd) < 0) {
printf("cannot close \"%s\"\n", filename);
return -1;
}
printf("\n");
}
return 0;
}
Below is an example of what it should look like (apart from the ./catraw's output which is incorrect). (ELF header and instructions are acquired from nasm, strace, and cat.)
elf_header='\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\2\0\3\0\1\0\0\0T\200\4\0104\0\0\0\0\0\0\0\0\0\0\0004\0 \0\1\0\0\0\0\0\0\0\1\0\0\0\0\0\0\0\0\200\4\10\0\200\4\10T\0\0\0T\0\0\0\5\0\0\0\0\20\0\0'
instructions='\263*f1\300f#\315\200'
printf "$elf_header$instructions" > return_42
chmod +x return_42
./return_42 # test run to see if it actually works
echo $? # echo return code of ./return_42
strace -s 4096 cat ./return_42
gcc catraw.c --static -o catraw
strace ./catraw -1 ./return_42
./catraw -1 ./return_42
[PROGRAM ] \177ELF\001\001\001\0\0\0\0\0\0\0\0\0\002\0\003\0\001\0\0\0T\200\004\0104\0\0\0\0\0\0\0\0\0\0\04\0 \0\001\0\0\0\0\0\0\0\001\0\0\0\0\0\0\0\0\200\004\010\0\200\004\010T\0\0\0T\0\0\0\005\0\0\0\0\020\0\0\263*f1\300f#\315\200
This is a bit unclear (not sure about all the assembly), but something like this:
#include <ctype.h>
// Format the character 'c' (which should be cast from char) into a
// string. Will use backslash-escaped form for non-printables.
void tostring(char *buf, size_t buf_max, unsigned int c)
{
if(isprint(c))
{
snprintf(buf, buf_max, "%c", c);
}
else
{
snprintf(buf, buf_max, "\\%3o", c);
}
}
This builds "\177" when called with c = 0177.
And yes, obviously the call to snprintf() in the first case can be factored out for printables.

C program runs fine locally, but segfaults on remote server

I have a command line game I wrote that runs properly locally, but segfaults on a remote server. I haven't been able to find out why this is the case.
Local:
Remote:
There clearly is an issue somewhere around where POSSIBLE CONNECTIONS are gathered/displayed.
Here's the full program. This issue may be happening around line 190, as that's where the POSSIBLE CONNECTIONS logic is. I have a feeling it's a problem with my strncpy line, as there is very specific memory manipulation going on there, but I could be wrong.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
struct stat st = {0};
const char * ROOM_NAMES[] = {"Water", "Fire", "Wind", "Earth", "Plasma", "DarkMatter", "Air", "Ice", "Rock", "Lava"};
int i,j;
char directory[20];
char *rooms[7];
int connections[7][7] = {0};
int totalMoves = 0;
char roomChoice[20];
char *movesRecord[100];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void getRoomChoice() {
fflush(stdin);
scanf("%s", roomChoice);
fflush(stdin);
fflush(stdout);
}
void * getTime(void *arg) {
pthread_mutex_lock(&mutex);
FILE *file = fopen("currentTime.txt", "w");
time_t curtime;
struct tm *loc_time;
curtime = time (NULL);
loc_time = localtime (&curtime);
fprintf(file, "%s\n", asctime (loc_time));
// printf("\n%s\n", asctime (loc_time));
fclose(file);
pthread_mutex_unlock(&mutex);
}
void * createRooms() {
// Create directory
int pid = getpid();
char prefix[] = "eldridgt.";
sprintf(directory, "%s%d", prefix, pid);
if (stat(directory, &st) == -1) {
mkdir(directory, 0700);
}
// Create room files
for(i=0; i<7; i++) {
int random;
char filePath[100];
int connectionArr[10];
memset(connectionArr, 0, sizeof connectionArr);
random = rand() % 10; // Random number 0-9
if (connectionArr[random] == 0) { // If room not used
sprintf(filePath,"%s/%s", directory, ROOM_NAMES[random]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "ROOM NAME: %s\n", ROOM_NAMES[random]); // Add room name
fclose(file);
rooms[i] = ROOM_NAMES[random];
connectionArr[random] = 1; // Room has been used
}
}
return rooms;
}
void * createConnections() {
for(i=0; i<7; i++) {
int connectionCount = rand() % 4 + 3; // Random number 3-6
int currentCount = 0;
for(j=0; j<7; j++) {
currentCount = currentCount + connections[i][j];
}
while (currentCount < connectionCount+1) {
int random = rand() % 7;
while (random == i) {
random = rand() % 7; // If random == current, reset random
}
// Set connections between both rooms
connections[i][random] = 1;
connections[random][i] = 1;
currentCount++;
}
}
}
void * connectionsToFiles() {
for(i=0; i<7; i++) {
int connectionCount = 1;
for(j=0; j<7; j++) {
if(connections[i][j] == 1) {
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "CONNECTION %d: %s\n", connectionCount, rooms[j]);
fclose(file);
connectionCount++;
}
}
}
}
void * roomTypesToFiles() {
for(i=0; i<7; i++) {
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "a");
switch(i) {
case 0 :
fprintf(file, "ROOM TYPE: START_ROOM\n");
break;
case 6 :
fprintf(file, "ROOM TYPE: END_ROOM\n");
break;
default :
fprintf(file, "ROOM TYPE: MID_ROOM\n");
}
fclose(file);
}
}
isEndRoom(idx) {
movesRecord[totalMoves - 1] = rooms[idx];
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[idx]);
char roomType[20];
int lineNumber = 1;
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[256];
while(fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
while(fgets(line, sizeof line, file) != NULL) {
if(lineNumber == totaLines) {
int length = strlen(line) - 11;
strcpy(roomType, line+11);
roomType[length-1] = '\0';
}
lineNumber++;
}
// Check if this is the end room
if(strncmp(roomType, "END", 3) == 0) {
printf("YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!\n");
printf("YOU TOOK %d STEPS. YOUR PATH TO VICTORY WAS:\n", totalMoves - 1);
for(i=1; i<totalMoves; i++) {
printf("%s\n", movesRecord[i]);
}
return 1; // End was reached
} else {
return 0; // End was not reached
}
}
void * playGame(idx) {
totalMoves++;
printf("\n");
if(isEndRoom(idx)) {
exit(0);
}
while(1) {
char filePath[100];
sprintf(filePath,"%s/%s", directory, rooms[idx]);
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[100];
while(fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
int lineNumber = 0;
char *roomChoices[6][20];
while(fgets(line, sizeof line, file) != NULL) { // Current room name
if(lineNumber == 0) {
char roomName[20];
int length = strlen(line) - 11;
strcpy(roomName, line+11);
roomName[length-1] = '\0';
printf("CURRENT LOCATION: %s\n", roomName);
}
else if(lineNumber == 1) { // First room choice option
printf("POSSIBLE CONNECTIONS: ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line+14);
roomName[length-1] = '\0';
printf("%s", roomName);
strcpy(roomChoices[lineNumber - 1], roomName);
}
else if(lineNumber > 1 && lineNumber < totaLines - 1) { // Subsequent room choice options
printf(", ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line+14);
roomName[length-1] = '\0';
printf("%s", roomName);
fflush(stdout);
strcpy(roomChoices[lineNumber - 1], roomName);
}
else {
printf(".");
fflush(stdout);
}
lineNumber++;
}
fclose(file);
printf("\nWHERE TO? >");
getRoomChoice(); // Get next room choice
if (strcmp(roomChoice, "time") == 0) {
pthread_t thread;
int rc = pthread_create(&thread, NULL, &getTime, NULL);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
pthread_mutex_lock(&mutex);
sleep(1);
FILE *file = fopen("currentTime.txt", "r");
char currentTime[25];
fgets(currentTime, sizeof currentTime, file);
printf("\n%s\n\n", currentTime);
pthread_mutex_unlock(&mutex);
} else {
for(i=0; i<totaLines-2; i++) {
if(strcmp(roomChoices[i], roomChoice) == 0) {
for(j=0; j<7; j++) {
if(strcmp(rooms[j], roomChoice) == 0) { // If the room is equal to roomChoice
playGame(j); // Make playGame call for new room
}
}
}
}
printf("\nHUH? I DON’T UNDERSTAND THAT ROOM. TRY AGAIN.\n\n");
fflush(stdout);
fflush(stdin);
}
}
}
int main() {
createRooms();
createConnections();
connectionsToFiles();
roomTypesToFiles();
playGame(0);
return 0;
}
I too got segfault and tried to fix the code. Now it did run after some changes.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <memory.h>
struct stat st = {0};
char *ROOM_NAMES[] = {"Water", "Fire", "Wind", "Earth", "Plasma", "DarkMatter", "Air", "Ice", "Rock", "Lava"};
int i, j;
char directory[20];
char *rooms[7];
int connections[7][7] = {0};
int totalMoves = 0;
char roomChoice[20];
char *movesRecord[100];
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void getRoomChoice() {
fflush(stdin);
scanf("%s", roomChoice);
fflush(stdin);
fflush(stdout);
}
void *getTime(void *arg) {
pthread_mutex_lock(&mutex);
FILE *file = fopen("currentTime.txt", "w");
time_t curtime;
struct tm *loc_time;
curtime = time(NULL);
loc_time = localtime(&curtime);
fprintf(file, "%s\n", asctime(loc_time));
// printf("\n%s\n", asctime (loc_time));
fclose(file);
pthread_mutex_unlock(&mutex);
}
void *createRooms() {
// Create directory
int pid = getpid();
char prefix[] = "eldridgt.";
sprintf(directory, "%s%d", prefix, pid);
if (stat(directory, &st) == -1) {
mkdir(directory, 0700);
}
// Create room files
for (i = 0; i < 7; i++) {
int random;
char filePath[100];
int connectionArr[10];
memset(connectionArr, 0, sizeof connectionArr);
random = rand() % 10; // Random number 0-9
if (connectionArr[random] == 0) { // If room not used
sprintf(filePath, "%s/%s", directory, ROOM_NAMES[random]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "ROOM NAME: %s\n", ROOM_NAMES[random]); // Add room name
fclose(file);
rooms[i] = ROOM_NAMES[random];
connectionArr[random] = 1; // Room has been used
}
}
return rooms;
}
void *createConnections() {
for (i = 0; i < 7; i++) {
int connectionCount = rand() % 4 + 3; // Random number 3-6
int currentCount = 0;
for (j = 0; j < 7; j++) {
currentCount = currentCount + connections[i][j];
}
while (currentCount < connectionCount + 1) {
int random = rand() % 7;
while (random == i) {
random = rand() % 7; // If random == current, reset random
}
// Set connections between both rooms
connections[i][random] = 1;
connections[random][i] = 1;
currentCount++;
}
}
}
void *connectionsToFiles() {
for (i = 0; i < 7; i++) {
int connectionCount = 1;
for (j = 0; j < 7; j++) {
if (connections[i][j] == 1) {
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "ab+");
fprintf(file, "CONNECTION %d: %s\n", connectionCount, rooms[j]);
fclose(file);
connectionCount++;
}
}
}
}
void *roomTypesToFiles() {
for (i = 0; i < 7; i++) {
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[i]);
FILE *file = fopen(filePath, "a");
switch (i) {
case 0 :
fprintf(file, "ROOM TYPE: START_ROOM\n");
break;
case 6 :
fprintf(file, "ROOM TYPE: END_ROOM\n");
break;
default :
fprintf(file, "ROOM TYPE: MID_ROOM\n");
}
fclose(file);
}
}
int isEndRoom(int idx) {
movesRecord[totalMoves - 1] = rooms[idx];
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[idx]);
char roomType[20];
int lineNumber = 1;
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[256];
while (fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
while (fgets(line, sizeof line, file) != NULL) {
if (lineNumber == totaLines) {
int length = strlen(line) - 11;
strcpy(roomType, line + 11);
roomType[length - 1] = '\0';
}
lineNumber++;
}
// Check if this is the end room
if (strncmp(roomType, "END", 3) == 0) {
printf("YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!\n");
printf("YOU TOOK %d STEPS. YOUR PATH TO VICTORY WAS:\n", totalMoves - 1);
for (i = 1; i < totalMoves; i++) {
printf("%s\n", movesRecord[i]);
}
return 1; // End was reached
} else {
return 0; // End was not reached
}
}
void *playGame(int idx) {
totalMoves++;
printf("\n");
if (isEndRoom(idx)) {
exit(0);
}
while (1) {
char filePath[100];
sprintf(filePath, "%s/%s", directory, rooms[idx]);
FILE *file = fopen(filePath, "r");
int totaLines = 0;
char line[100];
while (fgets(line, sizeof line, file) != NULL) {
totaLines++; // Line count of room file
}
fclose(file);
file = fopen(filePath, "r");
int lineNumber = 0;
char roomChoices[6][20];
while (fgets(line, sizeof line, file) != NULL) { // Current room name
if (lineNumber == 0) {
char roomName[20];
int length = strlen(line) - 11;
strcpy(roomName, line + 11);
roomName[length - 1] = '\0';
printf("CURRENT LOCATION: %s\n", roomName);
} else if (lineNumber == 1) { // First room choice option
printf("POSSIBLE CONNECTIONS: ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line + 14);
roomName[length - 1] = '\0';
printf("%s", roomName);
strcpy(roomChoices[lineNumber - 1], roomName);
} else if (lineNumber > 1 && lineNumber < totaLines - 1) { // Subsequent room choice options
printf(", ");
fflush(stdout);
char roomName[20];
int length = strlen(line) - 14;
strcpy(roomName, line + 14);
roomName[length - 1] = '\0';
printf("%s", roomName);
fflush(stdout);
strcpy(roomChoices[lineNumber - 1], roomName);
} else {
printf(".");
fflush(stdout);
}
lineNumber++;
}
fclose(file);
printf("\nWHERE TO? >");
getRoomChoice(); // Get next room choice
if (strcmp(roomChoice, "time") == 0) {
pthread_t thread;
int rc = pthread_create(&thread, NULL, &getTime, NULL);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
pthread_mutex_lock(&mutex);
sleep(1);
FILE *file = fopen("currentTime.txt", "r");
char currentTime[25];
fgets(currentTime, sizeof currentTime, file);
printf("\n%s\n\n", currentTime);
pthread_mutex_unlock(&mutex);
} else {
for (i = 0; i < totaLines - 2; i++) {
if (strcmp(roomChoices[i], roomChoice) == 0) {
for (j = 0; j < 7; j++) {
if (strcmp(rooms[j], roomChoice) == 0) { // If the room is equal to roomChoice
playGame(j); // Make playGame call for new room
}
}
}
}
printf("\nHUH? I DON’T UNDERSTAND THAT ROOM. TRY AGAIN.\n\n");
fflush(stdout);
fflush(stdin);
}
}
}
int main() {
createRooms();
createConnections();
connectionsToFiles();
roomTypesToFiles();
playGame(0);
return 0;
}
Test
rooms
CURRENT LOCATION: Earth
POSSIBLE CONNECTIONS: th, Air, Ice, DarkMatter, Earth, DarkMatter, Earth, Air, DarkMatter, DarkMatter, RT_ROOM.
WHERE TO? >Air
YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!
YOU TOOK 1 STEPS. YOUR PATH TO VICTORY WAS:
Air
Process finished with exit code 0

Calling my function, causes the program to crash - C | 3DS Homebrew

I've been writing a homebrew for the Nintendo 3DS, which is written in C. It simply parses a JSON file and prints it onto the screen. The problem is that after parsing and printing it on the screen, it just crashes.
Code:
char JSON_FILE[] = "jsbr-ford-mustang.json";
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) {
if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start &&
strncmp(json + tok->start, s, tok->end - tok->start) == 0) {
return 0;
}
return -1;
}
const char * parse_json(char* value) {
u8* file_buffer; FILE *file = fopen(JSON_FILE,"rb"); if (file == NULL) printf("Error.\n");
fseek(file,0,SEEK_END); off_t size = ftell(file); fseek(file,0,SEEK_SET); file_buffer=malloc(size);
if(!file_buffer) printf("Error.\n");
off_t bytesRead = fread(file_buffer,1,size,file); fclose(file);
if(size!=bytesRead) printf("Error.\n");
int i; int r;
jsmn_parser p; jsmntok_t t[128]; jsmn_init(&p);
r = jsmn_parse(&p, file_buffer, size, t, sizeof(t)/sizeof(t[0]));
if (r < 0) {
printf("Failed to parse JSON: %d\n", r);
return 1;
}
if (r < 1 || t[0].type != JSMN_OBJECT) {
printf("Object expected\n");
return 1;
}
printf("Debug START\n");
for (i = 1; i < r; i++) {
if (jsoneq(file_buffer, &t[i], value) == 0) {
printf("Debug 1\n");
break;
}
printf("Debug 2\n");
}
printf("Debug 3\n");
return printf("%.*s\n", t[i+1].end-t[i+1].start, file_buffer + t[i+1].start);
}
int main() {
gfxInitDefault();
consoleInit(GFX_TOP,NULL);
printf("P1\n");
printf("Description: %s",parse_json("description"));
printf("P2\n");
printf("Sync spacing: %s",parse_json("synchronization_spacing_us"));
while (aptMainLoop()) {
hidScanInput(); u32 kDown = hidKeysDown();
if(kDown & KEY_START) {
consoleClear();
break;
}
gfxFlushBuffers();
gfxSwapBuffers();
}
gfxExit();
return 0;
}
Debug output:
P1
Debug START
Debug 2
Debug 2
Debug 1
Debug 3
Ford Mustang, 40MHz, No. 23019
Here is a video of what happens: https://www.youtube.com/watch?v=zpt_BEMyIOc
Here is the GitHub repo that I have for it: https://github.com/lavanoid/3DS_JSON_Parser
from cplusplus.com regarding the return value of printf():
On success, the total number of characters written is returned.
If a writing error occurs, the error indicator (ferror) is set and a negative number is returned.
If a multibyte character encoding error occurs while writing wide characters, errno is set to EILSEQ and a negative number is returned.
you cannot do this: return printf("%.*s\n", t[i+1].end-t[i+1].start, file_buffer + t[i+1].start);
because your function needs to return a const char *, not an int, which is returned from printf().
You should use sprintf() to print the string you want into a buffer (tempString for example)
static char *tempString;
...
if(tempstring != NULL) {
free(tempString);
tempString = NULL;
}
tempString = (char *)malloc(t[i+1].end-t[i+1].start+1);
if(tempString != NULL) {
sprintf(tempString,"%s", file_buffer + t[i+1].start);
return (const char *)tempString;
} else {
return "malloc error!";
}

Write a WC simulator in C with different Child Processes [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Here is the final result i got so far for a simulator of wc linux command. I have to accomplish an output like this
This is child process 0, the number of lines is x
This is child process 1, the number of words is y
This is child process 2, the number of lines is z
The code i wrote is this one:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(FILE *f){
int count = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(FILE *f){
int countW = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
if (ch == ' ')
countW++;
}
return countW;
}
int countChars(FILE *f){
int chars = 0;
char ch;
while ((ch = fgetc(f)) != EOF){
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount += countLines(file);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount += countWords(file);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(file);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}
This is the actual output i am getting:
% ./a.out mywc.c
This is child proccess 2, and the number of words is 0
This is child proccess 1, and the number of lines is 64
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 2, and the number of words is 0
This is child proccess 3, and the number of characters is 0
This is child proccess 3, and the number of characters is 0
What am I doing Wrong here? I am very new to C programming so not sure what i am missing.
Thanks.
EDIT
Exited the exit codes but can not get the word count and the character count right now.
The right code for my problem is here:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
char* concat(char *s1, char *s2)
{
char *result = malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int countLines(char *f){
FILE *file = fopen(f, "r");
int count = 0;
char ch;
while ((ch = fgetc(file)) != EOF){
if (ch == '\n')
count++;
}
return count;
}
int countWords(char *f){
char buffer[1];
FILE *file = fopen(f, "r");
int countW = 0;
enum states { WSP, WRD };
int state = WSP;
char last = ' ';
while (read(fileno(file),buffer,1) == 1 )
{
if ( buffer[0]== ' ' || buffer[0] == '\t' || buffer[0]=='\n' )
{
state = WSP;
}
else
{
if ( state == WSP )
{
countW++;
}
state = WRD;
}
last = buffer[0];
}
return countW;
}
int countChars(char *f){
FILE *file = fopen(f, "r");
int chars = 0;
char ch;
while ((ch = fgetc(file))){
if (ch == EOF) break;
chars++;
}
return chars;
}
int main(int argc, char** argv)
{
int lineCount = 0;
int wordCount = 0;
int charCount = 0;
int n = 3;
int i,status;
int pids[3];
char *theprogram = argv[0];
char *thefile = argv[1];
if ( argc !=2 )
{
printf( "Help: %s filename\n", argv[0]);
}
else{
FILE *file = fopen( argv[1], "r");
if(file == 0){
char *sub = concat(theprogram, ": ");
char *middle = concat(sub, thefile);
perror(middle);
}
else{
for (i = 0; i < n; i++) {
pids[i] = fork();
if ( pids[i] < 0) {
perror("fork");
exit(-1);
} else if (pids[i] == 0) {
if (i==0){
lineCount = countLines(argv[1]);
printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount);
exit(0);
}
else if (i==1){
wordCount = countWords(argv[1]);
printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount);
exit(0);
}
else {
charCount += countChars(argv[1]);
printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount);
exit(0);
}
}
}
return 0;
}
}
}

Create a file or go to line n of that file

I've been working on this C programming assignment and I just can't seem to find out why it is not behaving the way I expect it to be behaving. The program is supposed to run, and there are 3 possible options for commands 0, -n, and n, where n is a positive integer.
When I execute the program, and type 0 as the command (which should create a file if one has not already been created) it just loops back to asking me to enter a command.
The commands -n and n go to the line specified by n and seeks to it. n prints line n, whereas -n prints all lines from n onward until it can no longer read from the text file.
Would greatly appreciate it if somebody could give me a hint or two and steer me in the right direction.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define BUFSIZE 256
#define LINESIZE 1024
int write(FILE *fp);
int grade_validation(int grade);
int id_validation(char studentid[]);
int display(FILE *fp, int cmd);
int display_all(FILE *fp, int cmd);
int main(int argc, char *argv[]) {
if(argc != 2) {
perror("invalid number of args");
return 1;
} else {
FILE *fp;
if((fp = fopen(argv[1], "wb+")) == 0) {
perror("fopen");
return 1;
}
write(fp);
fclose(fp);
}
return 0;
}
int write(FILE* fp) {
int grade;
char studentid[BUFSIZE];
char input[BUFSIZE];
int cmd;
while(1) {
printf("Input 0 to append, n to view, or -n to view all records starting from n.\n");
if(!fgets(input, LINESIZE, stdin)) {
clearerr(stdin);
return 0;
}
if((sscanf(input, "%d", &cmd) == 1)) {
if(cmd == 0) {
if((id_validation(studentid)) != 1 || (grade_validation(&grade) == -1)) {
continue;
}
fprintf(fp, "%s %3d ", studentid, grade);
} else if(cmd > 0) {
display(fp, cmd);
} else if(cmd < 0) {
display_all(fp, cmd);
}
}
}
}
int grade_validation(int grade) {
char input[BUFSIZE];
FILE *fp;
if(grade >= 0 && grade <= 100) {
return 1;
}
if(sscanf(input, "%d", &grade) == 1) {
if((grade_validation(grade)) == 1) {
if(fprintf(fp, "%3d", grade) == 0) {
return 0;
}
printf("Grade recorded successfully.\n");
return 1;
}
}
return 0;
}
int id_validation(char studentid[]) {
char input[BUFSIZE];
FILE *fp;
size_t i = 0;
if(strlen(studentid) == 9) {
for(i = 0; i < 9; i++) {
if(isdigit(studentid[i])) {
return 1;
}
}
}
if(sscanf(input, "%s", studentid) == 1) {
if((id_validation(studentid)) == 1) {
if(fprintf(fp, "%s", studentid) == 0) {
return 0;
}
printf("Student ID recorded successfully.\n");
return 1;
}
}
return 0;
}
int display(FILE *fp, int cmd) {
char studentid[BUFSIZE];
int grade;
if(!fgets(cmd, BUFSIZE, fp)) {
clearerr(stdin);
return 0;
}
fseek(fp, cmd, SEEK_SET);
fprintf(stderr, "%s %3d", studentid, grade);
}
int display_all(FILE *fp, int cmd) {
char studentid[BUFSIZE];
int grade;
if(!fgets(cmd, BUFSIZE, fp)) {
clearerr(stdin);
return 0;
}
fseek(fp, cmd, SEEK_SET);
while((sscanf(studentid, grade, "%s %3d", cmd)) != EOF) {
fprintf(stderr, "%s %3d", studentid, grade);
}
}
You're trying to validate the uninitialized studentid and grade.
Also, you pass &grade to grade_validation, which expects and integer.
This would cause a warning, which should make you figure out something is wrong. Always compile with warnings enabled, and treated as errors (in gcc, -Wall -Werror).

Resources