Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.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++ 为什么我要在这里获得一个EXC\u BAD\u访问权限?我如何才能使它工作?_C++_String_Strtok - Fatal编程技术网

C++ 为什么我要在这里获得一个EXC\u BAD\u访问权限?我如何才能使它工作?

C++ 为什么我要在这里获得一个EXC\u BAD\u访问权限?我如何才能使它工作?,c++,string,strtok,C++,String,Strtok,我试图使我的代码能够分离到客户数据库中(它由许多空格分隔,而不是制表符)。我尝试使用strtok,但遇到了EXC\u BAD\u访问错误。以下是我的main.cpp代码: #include <iostream> #include <fstream> #include <string> #include <sstream> #include "Cust.h" using namespace std; int main (int argc, char

我试图使我的代码能够分离到客户数据库中(它由许多空格分隔,而不是制表符)。我尝试使用strtok,但遇到了EXC\u BAD\u访问错误。以下是我的main.cpp代码:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Cust.h"
using namespace std;

int main (int argc, char * const argv[]) {
    Cust customers[500];
 int idx = 0;
 string tmpString = "";
 string tmpAcctFN = "";
 string tmpAcctLN = "";
 ifstream input("P3_custData.txt");
 while (!input.eof()){
  getline(input,tmpString);
  tmpString.insert(0,"");
  customers[idx].setAcctNum(atoi(strtok((char *)tmpString.c_str()," ")));
  customers[idx].setAcctFN(strtok(NULL," "));
  customers[idx].setAcctLN(strtok(NULL," "));
  //customers[idx].setCurrBalance(atof(strtok((char *) tmpString.c_str()," ")));
 }
 cout << "return 0;";
    return 0;
}
#包括
#包括
#包括
#包括
#包括“客户h”
使用名称空间std;
int main(int argc,char*const argv[]{
客户[500];
int-idx=0;
字符串tmpString=“”;
字符串tmpAcctFN=“”;
字符串tmpAcctLN=“”;
ifstream输入(“P3_custData.txt”);
而(!input.eof()){
getline(输入,tmpString);
tmpString.插入(0,“”);
客户[idx].setAcctNum(atoi(strtok((char*)tmpString.c_str(),“”));
客户[idx].setAcctFN(strtok(NULL)(“”);
客户[idx].setAcctLN(strtok(NULL)(“”);
//客户[idx].setCurrBalance(atof(strtok((char*)tmpString.c_str(),“”));
}

cout试图修改由
std::string::c_str()
方法返回的字符串是非法的。
strtok
将进行这样的尝试(您必须丢弃返回字符串的常量这一事实是一个死的赠品)。换句话说,您不能对
std::string::c_str()的结果使用
strtok


要么去掉
strtok
(更好),要么创建字符串的独立可修改副本,并在其上使用
strtok
(更糟)。

c\u str
方法将返回指向
const
数据的指针。一种方法是替换:

customers[idx].setAcctNum(atoi(strtok((char *)tmpString.c_str()," ")));
customers[idx].setAcctFN(strtok(NULL," "));
customers[idx].setAcctLN(strtok(NULL," "));
与:

这将为您提供一个重复的可写字符串,您可以在该字符串上运行
strok

我通常不喜欢C++代码中使用旧的C类东西,但我也很实用地获得代码。可能有更多的“C++”的方式。 而且,如果您的实现没有
strdup
(我认为这不是标准的一部分):

更新:

Anthony,根据您问题的更新,如果您仍然收到错误,那么可能是因为字符串不是您期望的。仔细想想,您不应该从写入
c_str
的结果中获得
EXC_BAD_访问
,因为从技术上讲,内存不是只读的。
EXC_BAD_访问
应该打开如果您试图写入只读内存(或地址空间之外),则可能会发生这种情况。正如一位评论员所指出的,
c_str
可能会在某些简单情况下返回指向只读内存的指针,但如果您的文件有复杂的行,则不太可能出现这种情况

在这两种情况下,复制到可变字符串将修复它

我认为可能发生的情况是,您的一个
strtok
s返回NULL。如果您正在处理一行少于三个字段(例如,“hello here”,其中第三个
strtok
将返回NULL),则会出现这种情况

在调用
strtok
之前,打印出代码中的字符串:

std::cerr << "[" << s << "]" << std::endl;
std::cerr
strtok()
如果没有剩余的令牌,将返回
NULL
。如果您将该指针交给
std::string
的构造函数或赋值运算符,则必须进行检查

char* token = ::strtok(0, " ");
if(!token) {
    // handle error
}

仍然考虑使用字符串流或其他更多的C++类功能来避免首先掉入这些陷阱。

考虑到我处于一个while循环中的事实,我会怎么做?如果你发现自己丢掉了<代码> const <代码> -----一个变量,你可能做了一些错误的事情。要摆脱
strtok()
选项包括
string::find()
或类似于boosts string算法的东西。@Anthony,我认为您的问题是输入行格式错误-请参阅我关于如何检测和解决它的更新。
std::string
的许多实现都会返回指向空字符串文本
的指针当字符串为空时,从
c_str()
读取。这是只读内存。
char *strdup (const char *s) {
    char *d = (char *)(malloc (strlen (s) + 1));
    if (d == NULL) return NULL;
    strcpy (d,s);
    return d;
}
std::cerr << "[" << s << "]" << std::endl;
char* token = ::strtok(0, " ");
if(!token) {
    // handle error
}