【问题标题】:Delete a line from a csv file c++从csv文件c ++中删除一行
【发布时间】:2020-12-17 09:03:44
【问题描述】:

这里我有一个读入向量的文件

typedef struct contacts 
{
    string name;   //{jhonathan , anderson , felicia}
    string nickName; //{jhonny  , andy , felic}
    string phoneNumber; // {13453514 ,148039 , 328490}
    string carrier;  // {atandt , coolmobiles , atandt }
    string address; // {1bcd , gfhs ,jhtd }

} contactDetails;

vector <contactDetails> proContactFile;

我想让用户从文件中删除联系人记录。为此我编写了一个代码。但是从我编写的代码中它会从文件中删除所有联系人详细信息。但我想要的是什么时候用户键入 name 然后程序应该只删除 name 并且相关的 nickname,carrier,phone numberaddress 属于该名称。这是我编写的代码

    string readString, selectContact;
    cout << "Enter the name you want to delete" << endl;
    cin >> selectContact;
    ifstream fin;
    fin.open(contactsFile); 
    if (!fin.is_open())
    {
        cout << "Unable to open Contacts.csv, please make sure file exists!" << endl;
    }
   
    ofstream fout;
    fout.open("temp.csv" , ios::out);

    while (getline(fin, readString))
    {
        if (((readString = readString.find(selectContact), 0)) == 0)
        {
            fout << readString  <<',' << "\n";
            
        }
        cout << "Deleted Successfully" << endl;
        showTableContacts();
    }
    if (((readString = readString.find(selectContact), 0) != 0))
    {
        cout << "\n" << selectContact << " not found" << endl;
    }
   
    fout.close();
    fin.close();
    remove("Contact.csv");//Deletes contacts.csv file
    rename("temp.csv" , "Contact.csv");//Rename temp file as Contacts.csv
}

【问题讨论】:

  • 我很惊讶readString = readString.find 编译,它几乎肯定不会像你想象的那样做
  • string::find() 返回一个size_t。所以if (((readString = readString.find(selectContact), 0)) == 0) 并没有按照你的想法去做。此外,在执行文件操作时,您的代码会继续出现一些错误 - 这意味着它将删除原始的 Contact.csv 并将其替换为错误之前输出到 temp.csv 的任何内容。
  • @Peter 那么请你帮我一个更好的方法吗?
  • 执行此操作的直接方法:为您的结构联系人定义 > 运算符(对于 iostream 的读\写),通过 std::copy 将文件读入向量,使用 std::remove_if 和 std ::erase 从向量中删除元素,再次使用 std::copy 将向量写入文件

标签: c++ vector struct file-io


【解决方案1】:
if (((readString = readString.find(selectContact), 0)) == 0)

这条线有几个问题。

  1. readString.find(selectContact) 返回匹配的索引,如果未找到则返回 string::npos。从技术上讲,检查它在位置 0 是否完全匹配是可以的,但是,在您的情况下,如果您的字符串是“abcdefg”并且您搜索“abc”,它也会在不应该匹配的位置 0 匹配。您需要确保整个字段匹配,而不仅仅是它的第一个字符。 (在您的行中找到第一个“,”,然后确保从开头到逗号的所有字节都与您的联系人匹配。)

  2. 接下来考虑这部分:

    readString = readString.find(selectContact)

您正在将查找结果分配给您的字符串。也就是说,如果 find() 返回 3,您将为字符串分配 3,该字符串被解释为 ASCII 字符,现在您的 readString 包含一个带有垃圾的字节。 (在 ASCII 中,'A' 是 65,等等)

所以现在你的字符串被删除了,你的匹配索引是第一个字节中的内容(如果值在范围内,或者如果溢出,则为未定义的行为。)

  1. 这种形式的代码:

    如果 (xxx, 0)

正在使用 逗号运算符,它通过从左到右计算表达式来对表达式进行排序,应用副作用(但丢弃结果)并且完整的表达式计算为最右边表达式的值。无论 xxx 做什么(在你的情况下,xxx 是上面第 2 步中的代码,删除你的字符串),它的返回值都会被丢弃,整个表达式的计算结果为 0,它会转换为布尔值 false。每次。 (1,2,3) 计算结果为 3,等等。

因此:

(readString = readString.find(selectContact), 0)

总是评估为 0。并且

if (((readString = readString.find(selectContact), 0)) == 0)

总是删除你的字符串,然后测试 0==0 是否总是正确的。

此外,您几乎不想删除输入文件。重写它们已经够危险了,但是在这样做之前你必须绝对确定一切都成功了;否则,如果你的程序只删除输入文件而不是其他任何东西,它最终会导致很多痛苦。

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2018-08-15
    • 1970-01-01
    相关资源
    最近更新 更多