Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在编译时更改字符串宏_C++_String_C++11_Macros_Compilation - Fatal编程技术网

C++ 在编译时更改字符串宏

C++ 在编译时更改字符串宏,c++,string,c++11,macros,compilation,C++,String,C++11,Macros,Compilation,我正在开发一个独特的客户端,它必须在不同的机器上工作。在每台机器上,服务器都运行在不同的IP地址中,但该地址是已知的 我不想每次运行时都告诉客户端哪个是IP,所以我想在编译时告诉它 问题在于,当使用g++-DHOSTNAME=127.0.0.1进行编译时(也尝试使用双引号),编译器会说: error: too many decimal points in number ./include/Client.h:18:25: note: in expansion of macro ‘HOSTNAME’

我正在开发一个独特的客户端,它必须在不同的机器上工作。在每台机器上,服务器都运行在不同的IP地址中,但该地址是已知的

我不想每次运行时都告诉客户端哪个是IP,所以我想在编译时告诉它

问题在于,当使用
g++-DHOSTNAME=127.0.0.1
进行编译时(也尝试使用双引号),编译器会说:

error: too many decimal points in number
./include/Client.h:18:25: note: in expansion of macro ‘HOSTNAME’
我也尝试过使用localhost

error: ‘localhost’ was not declared in this scope
./include/Client.h:18:25: note: in expansion of macro ‘HOSTNAME’
还尝试使用一些在互联网上找到的东西

#define XSTR(x) STR(x)
#define STR(x)
编译错误:

./src/BSCClient.cpp:15:45: note: #pragma message: HOSTNAME: 
#pragma message("HOSTNAME: " XSTR(HOSTNAME))

./src/BSCClient.cpp:16:39: error: too few arguments to function ‘hostent* gethostbyname(const char*)’
  server = gethostbyname(XSTR(HOSTNAME));
在这一点上,我想也许宏不是处理这个问题的正确方法,但我不知道如何去做

如果有人对此有任何建议,我将不胜感激

编辑: 这些是代码

客户h:

#ifndef __CLIENT_HH__
#define __CLIENT_HH__

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#include <string>
#include <iostream>

using namespace std;

#define HOSTNAME 127.0.0.1
#define MAX_MESSAGE_LENGTH 10 

class Client {
private:
    string client_name;
    int sockfd, portno;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    error(const char *msg);

public:

    BSCClient (string name, int port);
    void identifyme();
    void sendData (string data);
    string recvData ();

    void closeSocket();
};

#endif
\ifndef\uuuu客户机\uhh__
#定义客户机__
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#定义主机名127.0.0.1
#定义最大消息长度10
类客户端{
私人:
字符串客户端名称;
int sockfd,端口号;
服务地址中的结构sockaddr\u;
结构主机*服务器;
错误(常量字符*消息);
公众:
BSCClient(字符串名称,int端口);
void identifime();
void sendData(字符串数据);
字符串recvData();
void closeSocket();
};
#恩迪夫
Client.cpp

#include "BSCClient.h"

#include <stdlib.h>
#include <time.h>

void BSCClient::error(const char *msg)
{
    perror(msg);
    exit(0);
}

Client::Client(string name, int port)
{
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    portno = port;
    client_name = name;

    if (sockfd < 0) 
        error("ERROR opening socket");

    server = gethostbyname(HOSTNAME);

    if (server == NULL) {
        fprintf(stderr,"ERROR, no such host\n");
        exit(0);
    }

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    bcopy((char *)server->h_addr, 
         (char *)&serv_addr.sin_addr.s_addr,
         server->h_length);
    serv_addr.sin_port = htons(portno);
    if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
        error("ERROR connecting");

    sendData(client_name);
}

void Client::identifyme() {
    FILE *fp;
    fp = popen("id -gn", "r");

    char text[6];
    fscanf(fp, "%s", text);
    pclose(fp);
    string data(text);
    sendData(data);
}

void Client::sendData (string data) {
    const char *sdata = data.c_str();
    int n;
    n = write(sockfd, sdata, strlen(sdata));
    if (n < 0) 
         error("ERROR writing to socket");
}

string Client::recvData () {
        int n;
        int bytes;
        char *longitud = new char[MAX_MESSAGE_LENGTH+1];
        n = read(sockfd, longitud, MAX_MESSAGE_LENGTH);
        if (n < 0) {
                error("ERROR recieving size of output");
        }
        bytes=atoi(longitud);
        //Para forzar el fin del string (ya que al imprimir el string hay veces que muestra caracteres de más)
        longitud[MAX_MESSAGE_LENGTH]='\0';
        char *data = new char[bytes];
        n = read(sockfd, data, bytes);
        if (n < 0)
                error("ERROR reading output");
        string ret(data);
        return ret;
} 

void Client::closeSocket() {
    close(sockfd);
}
#包括“BSCClient.h”
#包括
#包括
void BSCClient::错误(const char*msg)
{
佩罗尔(味精);
出口(0);
}
客户端::客户端(字符串名称,int端口)
{
sockfd=套接字(AF_INET,SOCK_STREAM,0);
端口号=端口号;
客户名称=名称;
if(sockfd<0)
错误(“打开套接字时出错”);
服务器=gethostbyname(主机名);
如果(服务器==NULL){
fprintf(stderr,“错误,没有这样的主机\n”);
出口(0);
}
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
b复制((字符*)服务器->h_地址,
(char*)和serv_addr.sin_addr.s_addr,
服务器->h_长度);
serv_addr.sin_port=htons(端口号);
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
错误(“连接错误”);
sendData(客户名称);
}
void客户端::identifyme(){
文件*fp;
fp=popen(“id-gn”,“r”);
字符文本[6];
fscanf(fp,“%s”,文本);
pclose(fp);
字符串数据(文本);
发送数据(数据);
}
无效客户端::发送数据(字符串数据){
const char*sdata=data.c_str();
int n;
n=写入(sockfd、sdata、strlen(sdata));
if(n<0)
错误(“写入套接字时出错”);
}
字符串客户端::recvData(){
int n;
整数字节;
char*longitud=新字符[最大消息长度+1];
n=读取(sockfd、longitud、最大消息长度);
if(n<0){
错误(“接收输出大小错误”);
}
字节=atoi(纵向);
//这条线的长度是多少
longitud[MAX_MESSAGE_LENGTH]='\0';
字符*数据=新字符[字节];
n=读取(sockfd,数据,字节);
if(n<0)
错误(“错误读取输出”);
字符串ret(数据);
返回ret;
} 
void客户端::closeSocket(){
关闭(sockfd);
}

您想将其硬编码到可执行文件中似乎有些奇怪。应该更灵活地使用
getenv(“MY\u SERVER\u ADDR”)
之类的工具,并在运行服务器之前设置环境变量。当然,你也可以做一些更典型的事情,把它当作命令行参数,但有些事情告诉我你已经决定不这么做了


如果您在Linux上,一个稍微奇怪的想法是将IP地址写入一个文本文件,并使用
ld
objcopy
从中创建一个ELF对象文件;然后,如果你真的想“硬编码”,你可以将其作为共享对象或静态对象加载到你的应用程序中。但我不确定为什么这比前面提到的选项更可取。

您必须避开双引号:

g++ -DHOSTNAME=\"127.0.0.1\"
否则,引号只是对您的shell
127.0.0.1
是您想要给
-DHOSTNAME
的值,如果该值有空格,则该值可能很有用,例如:

g++ -DMAGIC_NUMBER="150 / 5"
(此处,
MAGIC_编号
将替换为不带引号的
150/5

如果您希望引号成为宏的一部分(如在
#define HOSTNAME“127.0.0.1”
中),您必须对shell说它们是您给
-DHOSTNAME
的值的一部分,这可以通过转义它们来完成

编辑

另外,正如Angew所指出的,您误用了XSTR技巧。这是解决你问题的另一个办法,而不是我的答案

它确实是这样工作的:

#define XSTR(x) STR(x)
#define STR(x) #x
这样你就不必逃避引用

这两个宏将文本
127.0.0.1
更改为
“127.0.0.1”
XSTR
宏允许将
HOSTNAME
扩展到
127.0.0.1
,然后
STR
宏将其转换为
“127.0.0.1”
。如果直接使用
STR
宏,则最终将得到
的“HOSTNAME”
,而不是
“127.0.0.1”


我想我更喜欢转义解决方案,而不是在代码中使用包含两个宏的技巧,但这也行得通。

客户端上的实际代码是什么。h:18?@Niall不,它说的是相同的。对不起,我忘了写我已经试过了。@BorjaArias,好的,除了你已经发布的错误内容之外,发布产生错误的实际代码也可能有用。除非你甚至没有正确复制粘贴
XSTR
技巧。第二行应该是
#define STR(x)#x
。当然,你不应该盲目地将你不懂的互联网代码粘贴到生产代码中。我在一个多用户系统中工作,所以请看第二节