运行时的深奥C程序行为 - 代码没有按顺序运行

时间:2012-04-15 18:41:33

标签: c while-loop printf

我正在使用注册登录系统制作服务器聊天应用程序。在运行客户端代码时:我首先选择注册,然后在成功注册后,客户端代码提示我登录。然后我登录,它工作正常。我在客户端代码的if else块中实现了这两个东西。在此之后,我正在做一些事情,在那里我遇到了我生命中最有吸引力的错误之一。这是我的源代码,我在其中标记了有错误的区域(在main函数的末尾)并且还提到了那里的问题(问题的代码定义很容易)。
我也在代码后发布了输出。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <time.h>
#define PORT "1618" //the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once

static const int BUFFER_SIZE = 16*1024;
//get sockaddr ,IPv4 or IPv6:




void *get_in_addr(struct sockaddr *sa)
{
    if(sa->sa_family ==AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int registerYourself(int sockfd)
{   
    printf("2\n");
    char username[50], password[50],registerStatus[2];
    int return_value,choice;
    printf("You have chosen to register yourself\n");
    printf("Please enter a username and password\n");
    printf("Username:");
    scanf("%s",username);
    //printf("You entered %s\n",username);
    send(sockfd,username,sizeof(username),0); // sending username
    printf("\nPassword:");
    scanf("%s",password);    //sending password
    //printf("-- %s\n",password);
    send(sockfd,password,sizeof(password),0);           //sending password
    recv(sockfd,registerStatus,sizeof(registerStatus),0);//receiving from server that register is successful or not
    if(strcmp(registerStatus,"1")==0) //If register successful then promoting for log-in
        {
        printf("Registration successfull\n Please Log in\n");
        return_value=login(sockfd);
        return return_value;
        }
    else if(strcmp(registerStatus,"0")==0)// Asking user what to do
        {
        printf("Username already taken...Please try again with other username...\nPress:\t 1 to try again\n\t2 to quit");
        scanf("%d",&choice);
        switch(choice)
            {
            case 1:
                  send(sockfd,"1", 2, 0);
                registerYourself(sockfd);
                break;
            case 2:
                send(sockfd,"0",2,0);
                return 0;
            }           
        }
}

int login(int sockfd)
{   
    printf("3\n");
    char username[50],password[50],login_status[2];
    int choice;
    printf("You have chosen to login yourself\n");
    printf("Please enter a username and password\n");
    printf("Username:");
    scanf("%s",username);
//  printf("-- %s\n",username);
    send(sockfd,username,sizeof(username),0);
    send(sockfd,username,sizeof(username),0);//send username
    printf("\nPassword:");
    scanf("%s",password);
    //printf("-- %s\n",password);
    send(sockfd,password,sizeof(password),0);//send password
    recv(sockfd,login_status,sizeof(login_status),0); // //receiving from server that login is successful or not
    if(strcmp(login_status,"1")==0)
        {
        printf("login successfully 1\n");
        //while(1);// doing other job here
        return 1;
        }
        else if(strcmp(login_status,"0")==0)
        {
        printf("Wrong Username And/Or Password\nPress:\n__1)__To Enter Again  |  __2)__To Quit");
        scanf("%d",&choice);
        switch(choice)
            {
            case 1:
                send(sockfd,"1", 2, 0);// sending that user want to login again
                login(sockfd);
                break;
            case 2:
                send(sockfd,"0",2,0);// sending that user want to stop
                return 0;
            //TODO default case 
            }
        }
        //break;//case 2 ends
}


int main(int argc, char *argv[])
{
    char fname[50], s[INET6_ADDRSTRLEN], buf[MAXDATASIZE], username[50], password[50], registerStatus[2], login_status[2];
    int sockfd, numbytes,fp,i,rv, choice,iflogin=0;

    struct addrinfo hints, *servinfo, *p;

    if(argc != 2) 
        {
            fprintf(stderr,"usage: client hostname\n");
            exit(1);
        }

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;

        if((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) 
        {
            fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(rv));
            return 1;
        }

        //lopp through all the results and connect to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next) 
        {
            if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
                perror("client: socket");
                continue;
            }

            if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
            {
                close(sockfd);
                perror("client: connect");
                continue;
            }
            break;
        }

        if(p ==NULL) 
        {
            fprintf(stderr,"client: failed to connect\n");
            return 2;
        }

        inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
        printf("client : connecting to %s\n", s);

        freeaddrinfo(servinfo); // all done with this structure





**//////////////////////////       Here problem /////////////////////////**Code is continuous just to show you that problem is here.


//////////////////////////       Here problem /////////////////////////
//////////////////////////       Here problem /////////////////////////
//////////////////////////       Here problem /////////////////////////


        printf("\n----------------Menu-------------------------\n1.Register\n2.Log in\n");
        scanf("%d",&i); //here i am asking user whether to register or login and while running i choose to register 
        int status_value;   

            if(i==1)// I am going to enter in this loop
                {
                    send(sockfd,"1", 2, 0);//sending server that user want to register - work fine
                    printf("1\n");//work fine
                    status_value = registerYourself(sockfd);//this function ask me to register ang return 1 for success which is happening when I am running this code as:
                    if(status_value == 1)
                    {
                        printf("Logged in successful inside case 1\n"); // this prints
                        iflogin = 1;
                        printf("HERE 1-----------------\n");//this prints
                        printf("HERE 1-----------------\n");//this prints
                    }
                    else    //not get in this -obvious
                    {
                        printf("Bye!!!");   
                        printf("HERE 1!!!!!!!!!!!!!\n");        
                    }
                }
            if(i==2)// also dont go in this loop - obvious
            {
                printf("Inside case 2");
                send(sockfd,"2", 2, 0); //sending server that user want to login
                //status_value = login(sockfd);
                if(status_value == 1)
                    {
                    printf("Logged in successful inside case 2\n");
                    iflogin = 1;
                    }
                else    {
                    printf("Bye!!!");           
                    }

            }

        //fflush(stdout);
        //fflush(stdin);
        //fflush(stderr);

        // now some mytic thing is happening. this is not get printed and programmed get blocked [dont get stopped] just get blocked
        //if I commented the last while(1) [in the end] loop then everything works fine
        //if I commented the last while(1) and uncomment the sleep(5) statement t'outside here get printed after 5 seconds means after the sleep statement'
        //I have also tried to flush - but this shit is not flushing
        //pls tell me what is happening
        printf("Outside here");
        printf("Outside here");
        printf("Outside here");
        //sleep(5);
        if(iflogin==1)
        {
            printf("Logged in");
        }
        else
        {
            printf("Final Bye");
        }
        while(1); //doing other job
        close(sockfd);

        return 0;
}

output- showing blocked state of the code in the end run with while(1) as explained in the problem output-显示在结束运行中使用while(1)的代码的阻塞状态,如问题

中所述

1 个答案:

答案 0 :(得分:2)

如果标准输出是终端(否则为块缓冲),因此默认情况下,标准输出的printf()是行缓冲的,因此不打印该行。尝试:

printf("Outside here\n");

或添加

fflush(stdout);

printf()语句之后。 (编辑)但是,fflush(stdout)不能保证工作,因为允许实现将部分行丢弃到stdout(部分意味着不被\n终止)。要在安全(便携)方面,始终使用\n终止写入stdout的行。见C99 7.19.2第2段:

  

文本流是由字符组成的有序字符序列   行,每行由零个或多个字符加上a组成   终止换行符。最后一行是否需要   终止换行符是实现定义的。 [...]