在C中实现互斥的问题

时间:2017-05-12 03:02:49

标签: c multithreading mutex

我正在实施一个程序来读取包含房间名称,连接和房间类型的文件名。例如:

ROOM NAME: chicago
CONNECTION 1: sarasota
CONNECTION 2: columbus
CONNECTION 3: miami
CONNECTION 4: boston
ROOM TYPE: END_ROOM

该程序旨在向用户显示他们正在开始的房间,询问用户的输入,检查输入是终端房间还是其他连接。如果是另一个连接,则会再次显示提示。如果用户到达终端房间,则游戏结束。但是,我需要实现一个互斥锁,如果用户输入" time",则会创建一个文件,将时间写入其中,并显示在屏幕上。之后,再次为用户显示提示。当删除互斥锁实现时,我的代码工作正常。这是我在代码中使用互斥锁时所看到的内容。我似乎达到时间功能,程序似乎识别不正确的房间,但当一个"正确"房间进入光标只是返回,什么都不做。有关为什么我只在互斥实现上获得此行为的任何线索?

enter image description here

该程序如下,您是否看到任何可能导致此问题的内容?

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h> 
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>

//Read in the room data
//Perform the stat() function on the rooms directory in the same directory
//and open the file with the most recent st_mtime component of the returned stat struct

#define NUM_USED_ROOMS 7

char usedRooms[NUM_USED_ROOMS][256];
char roomFilePath[75];
char timeFilePath[75];
char* connections[NUM_USED_ROOMS];
int end = 0;
char input[20];
int numberOfSteps = -1;
char *steps[75];
int file_descriptor;
char timeText[100];
pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;


void * getTime() {
    pthread_mutex_lock(&myMutex);
    printf("You asked for the time!\n");
    pthread_mutex_unlock(&myMutex);
    return NULL;
}

//Check if the room number passed is the end
void isEnd(int roomNumber, char *dirName){

    //Counting the number of steps for the end of the program
    numberOfSteps++;
    steps[numberOfSteps - 1] = usedRooms[roomNumber];

    //Getting the name of the proper file
    sprintf(roomFilePath, "%s/%s", dirName, usedRooms[roomNumber]);
    char substring[20];
    int numLine = 1;

    FILE * filePointer;
    filePointer = fopen(roomFilePath, "r");
    int lines = 0;
    char buffer[256];
    while(fgets(buffer, sizeof(buffer), filePointer) != NULL){
        lines = lines + 1;
    }

    fclose(filePointer);

    //Opening the file to read to see if it is the end. If it is, assign end = 1.
    filePointer = fopen(roomFilePath, "r");
    while(fgets(buffer, sizeof(buffer), filePointer) != NULL) {

        if (numLine == lines)
        {
            strcpy(substring, buffer+11);   
        }
        numLine = numLine + 1;
    }

    if(strstr(substring, "END" ) != NULL) {
        end = 1;
    }
}

//Get the user input
void getInput() {

    fflush(stdin);
    scanf("%s", input);
    fflush(stdin);
    fflush(stdout);
}

void readFile(char *dirName){

    DIR *dir;
    struct dirent *ent;
    int i = 0;
    if ((dir = opendir (dirName)) != NULL) {
  /* print all the files and directories within directory */
        while ((ent = readdir (dir)) != NULL) {
            if (strncmp(ent->d_name,".",sizeof(ent->d_name)) == 0 ||
                strncmp(ent->d_name,"..",sizeof(ent->d_name)) == 0 )
            {

            } else {
                    strcpy(usedRooms[i],ent->d_name);
                    i++;
            }

        }
        closedir (dir);
    } else {
  /* could not open directory */
        perror ("");
    }

}

void playGame(int roomNumber, char * dirName){

    int i;
    printf("usedRooms is %s", usedRooms[roomNumber]);
    pthread_mutex_lock(&myMutex);
    pthread_t secondThread;
    pthread_create(&secondThread, NULL, getTime,NULL);


    //Check if the user guessed the end room
    if(end == 1) {

        fflush(stdout);
        return;
    }

    else{

        isEnd(roomNumber, dirName);
        if (end == 1)
        {
            fflush(stdout);
            return;
        }

    }

    int move = 1;
    while(move == 1) {

        //Open the file of the path of the room passed in
        sprintf(roomFilePath, "%s/%s", dirName, usedRooms[roomNumber]);
        FILE * filePointer;
        filePointer = fopen(roomFilePath, "r");
        int fileLines = 0;
        char line[256];

        //Count the lines in the file so I know how to traverse it
        while(fgets(line, sizeof line, filePointer) != NULL) {

            fileLines = fileLines + 1;
        }

        fclose(filePointer);

        filePointer = fopen(roomFilePath, "r");

        int currentLine = 0;


        //Create the array for the rooms that can be navigated to
        char gameRooms[6][30];

        while(fgets(line, sizeof line, filePointer) != NULL) {
            char *pos;
            if((pos = strchr(line, '\n')) != NULL) 
            {
                *pos = '\0';
            }

            //Print out the current room
            if (currentLine == 0)
            {
                char substring[20];
                strcpy(substring, line+11);
                printf("CURRENT LOCATION: %s\n", substring);
            } 
            //Print the first connection from this room
            else if (currentLine == 1){

                printf("POSSIBLE CONNECTIONS: ");
                fflush(stdout);
                char substring[20];
                strcpy(substring, line+14);
                printf("%s", substring);
                fflush(stdout);
                strcpy(gameRooms[currentLine - 1], substring);

            } 
            //Print the rest of the connections, comma separated
            else if (currentLine > 1 && currentLine < fileLines - 1) {
                printf(",");
                fflush(stdout);
                char substring[20];
                strcpy(substring, line+14);
                printf("%s", substring);
                fflush(stdout);
                strcpy(gameRooms[currentLine - 1], substring);
                //gameRooms[currentLine - 1] = substring;

            }
            else {

                printf(".");
                fflush(stdout);
            }

            currentLine = currentLine + 1;
        }
        fclose(filePointer);

        printf("\nWHERE TO?>");

        //Get the user input
        getInput();

        if(strcmp("time", input) == 0){
            pthread_mutex_unlock(&myMutex);
            pthread_join(secondThread, NULL);
            pthread_mutex_lock(&myMutex);
            pthread_create(&secondThread, NULL, getTime, NULL);
        }

        //Loop through the file to see if the input matches a room name in the array
        for(i = 0; i < fileLines - 2; i++) {

            if (strcmp(gameRooms[i], input) == 0) 
            {
                int j;
                for(j = 0; j < NUM_USED_ROOMS; j++) {

                    //If there is a match, play the game starting at the room entered
                    if(strcmp(usedRooms[j], input) == 0) {
                        printf("THE STRINGS MATCH usedRooms is %s "
                         "and input is %s\n",usedRooms[j],input);
                        playGame(j,dirName);
                    }
                }
                move = 0;
            }
        }
        //If the user's input didn't match the list of rooms
        if (move == 1) {

            printf("\nHUH? I DON'T UNDERSTAND THAT ROOM. TRY AGAIN. \n\n");
            fflush(stdout);
            fflush(stdin);
        }

    }


}


int main() {


      int newestDirTime = -1; // Modified timestamp of newest subdir examined
      char targetDirPrefix[32] = "walterer.rooms."; // Prefix we're looking for
      char newestDirName[256]; // Holds the name of the newest dir that contains prefix
      memset(newestDirName, '\0', sizeof(newestDirName));

      DIR* dirToCheck; // Holds the directory we're starting in
      struct dirent *fileInDir; // Holds the current subdir of the starting dir
      struct stat dirAttributes; // Holds information we've gained about subdir

      dirToCheck = opendir("."); // Open up the directory this program was run in

      if (dirToCheck > 0) // Make sure the current directory could be opened
      {
        while ((fileInDir = readdir(dirToCheck)) != NULL) // Check each entry in dir
        {
          if (strstr(fileInDir->d_name, targetDirPrefix) != NULL) // If entry has prefix
          {
            //printf("Found the prefex: %s\n", fileInDir->d_name);
            stat(fileInDir->d_name, &dirAttributes); // Get attributes of the entry

            if ((int)dirAttributes.st_mtime > newestDirTime) // If this time is bigger
            {
              newestDirTime = (int)dirAttributes.st_mtime;
              memset(newestDirName, '\0', sizeof(newestDirName));
              strcpy(newestDirName, fileInDir->d_name);
            }
          }
        }
      }

  closedir(dirToCheck);

  //Read the file at the specified directory
  readFile(newestDirName);

  int start;
  int i;
  for (i = 0; i < NUM_USED_ROOMS; i++)
  {
    memset(roomFilePath, '\0', sizeof(roomFilePath));
    sprintf(roomFilePath,"%s/%s", newestDirName, usedRooms[i]);
    char output[256];
    memset(output, '\0', sizeof(output));
    char* token;
    char* connectRoom;

    FILE *filePointer;
    filePointer = fopen(roomFilePath,"r");

    //Find the starting room and pass that into the playGame function
    if (filePointer == NULL)
    {
            printf("Unable to open file!\n");
    } else {
            while(!feof(filePointer)) {

                    fgets(output, 256, filePointer);
                    token = strtok(output, "\n");

                    if(strstr(token, "START") != NULL){
                            start = i;
                    }
            }
            fclose(filePointer);
    }
  }

  //Play the game with the starting room at the directory name
  playGame(start, newestDirName);

  printf("YOU HAVE FOUND THE END ROOM. CONGRATULATIONS!\n");
  printf("YOU TOOK %d STEPS. YOUR PATH TO VICTORY WAS: \n", numberOfSteps);
  for(i = 0; i < numberOfSteps; i++){

    printf("%s\n", steps[i]);
  }
  return 0;
}

0 个答案:

没有答案
相关问题