【问题标题】:pointer that is assigned value in function is blank after returning在函数中赋值的指针在返回后为空
【发布时间】:2017-05-29 11:31:23
【问题描述】:

创建一个将客户记录添加到文本文件的函数。 我已经制作了一个功能,可以修剪客户名称等的前导和最后一个空格,称为修剪空格。

函数 addrecord 用于处理记录在文件中的存储。它有 3 个参数(姓名/地址/电话)。在存储操作函数之前会使用 trimspaces 函数去除空格,然后将 3 个字符串合并为一个。

#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h> //mkdir
#include <stdio.h> //printf
#include <errno.h> //error number
#include <unistd.h> //access
#include <string.h> //strcat
#include <ctype.h> //isspace
#include <stdlib.h>//malloc

int checkFile();
int makeFile();
int addRecord(char* name, char* addr, char* phon);
int searchRec(int column, char* value);
char* getRec(int recNo);
int getRecNo();
char* trimspaces(char* string,char*ptr);


int addRecord(char* name, char* addr, char* phon){
    printf("\n- starting records addReord function -\n");   
    int success = 0;

    char* namt = trimspaces(name,namt);
    char* addt = trimspaces(addr,addt);
    char* phot = trimspaces(phon,phot);

    //this prints "trimmed words: , , " 
    printf("\n trimmed words: %s, %s, %s",namt,addt,phot);  


    /*
    char*combined1 = strcat(namt,"|");
    char*combined2 = strcat(combined1,addt);
    char*combined3 = strcat(combined2,"|");
    char*combined4 = strcat(combined3,phot);

    printf("\nwords combined: %s",combined4);

    */

    printf("\n- leaving records addrecord function -\n");
    return success;
}



char* trimspaces(char* string,char*ptr){
    printf("\n- entered trimspaces function -");    

    char *str= string;
    int slen = strlen(str); //string length
    int ctfor = 0; //counter forward
    int ctbak = 0; //counter back

    while(isspace(*str)){ str++; ctfor++; }; //count to start of word
    while(*str){str++;}; //go to end

    do{ str--; ctbak++; }while(isspace(*str)); //count from end to end of word

    int cbako = (slen - ctbak) + 1; //counter back reversed
    int wlen = cbako - ctfor; //get word length

    printf("\nstr_len:%d,counter_fore:%d,counter_bak:%d,cbakreversed:%d,wlen:%d",slen,ctfor,ctbak,cbako,wlen);  

    while(*str){ str--; }
    str++;

    while(isspace(*str)){
        str++; 
    }





    char newStr[wlen]; //char pointer gives segmentation fault
    memcpy(newStr,str,wlen);
    printf("\n--%s--",newStr);

    ptr = malloc(sizeof(newStr)+1);
    ptr = newStr;
    printf("\nPTR is : %s",ptr);

    return ptr;
    printf("\n- leaving trimspaces function -");
}


int main(){
    addRecord("kara","19,sams st","993328");

}

这是输出: (我希望 --text-- 之间的文本是去掉前导/结尾空格的字符串,并且要说 timmed words 行 - TRIMMED words: kara,19,sams st,993328)

- starting records addReord function -

- entered trimspaces function -
str_len:4,counter_fore:0,counter_bak:1,cbakreversed:4,wlen:4
--kara--
PTR is : kara
- entered trimspaces function -
str_len:10,counter_fore:0,counter_bak:1,cbakreversed:10,wlen:10
--19,sams st@--
PTR is : 19,sams st@
- entered trimspaces function -
str_len:6,counter_fore:0,counter_bak:1,cbakreversed:6,wlen:6
@--93328s W
@TR is : 993328s W
 TRIMMED words: , , 
- leaving records addrecord function -

我在 main 函数的输出中遇到了 2 个问题。首先是打印的字符串 - printf("\n TRIMMED words: %s, %s, %s",namt,addt,phot); 阅读:修剪过的词:,,, 我尝试了很多东西,但返回的变量总是空白。我想知道我是否正确使用了 malloc 和指针。

第二个问题是

--19,sams st@--
PTR is : 19,sams st@
@--93328s W
@TR is : 993328s W

我不知道@ 和 Ws 是从哪里来的。当我用不同的值测试 trimspaces 函数时,它打印出正确的结果。

我会注意到,我在终端上使用了 export PS1='\u@\h: ' 来获得更短的提示。

我应该怎么做才能让变量打印值?

【问题讨论】:

  • 在您对trimspaces 的调用中,参数namtaddtphot 未初始化。此代码具有未定义的行为。
  • ptr = malloc(...); ptr = ... 中,从malloc 返回的值丢失了。这是内存泄漏。
  • 你创建了一个局部变量newStr[wlen];。该变量(及其内容)在函数返回后消失。并且您复制的字符串不是以 NULL 结尾的。
  • trimspaces返回newStr(实际上是指向newStr的第一个元素的指针),这是一个局部数组,函数返回后就不存在了。这是未定义的行为。
  • 在许多平台上,char 是有符号类型(即它可以有一个负值)。将负值传递给 isspace 具有未定义的行为(除非它是 EOF)。这应该是isspace((unsigned char)*str)

标签: c string pointers malloc


【解决方案1】:

根据给出的反馈,我修改了代码以纠正一些错误。这段代码可能不太正确,并且仍然存在问题(显然,修剪空间函数的空白输入字符串会产生错误 - 我暂时不考虑这个问题并继续前进)

经过一番挖掘,我发现您需要将指针传递给指针 (**),以便 malloc 处理传递给不同函数的变量。仍然不能很好地理解这些原则,但它似乎有效。还在指针空间和字符数组上使用 strcat 而不是使用直接 = 运算符。

#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h> //mkdir
#include <stdio.h> //printf
#include <errno.h> //error number
#include <unistd.h> //access
#include <string.h> //strcat
#include <ctype.h> //isspace
#include <stdlib.h>//malloc

int addRecord(char* name, char* addr, char* phon);
void trimspaces(char* string,char**ptr);



int addRecord(char* name, char* addr, char* phon){
    printf("\n- starting records addReord function -\n");   
    int success = 0;

    char* namt = "";
    trimspaces(name,&namt);
    char* addt = "";
    trimspaces(addr,&addt);
    char* phot = "";
    trimspaces(phon,&phot);

    //this prints "trimmed words: , , " 
    printf("\n TRIMMED words: %s, %s, %s",namt,addt,phot);  

    printf("\n- leaving records addrecord function -\n");
    return success;
}



void trimspaces(char* string, char** ptr){
    printf("\n- entered trimspaces function -");    
    //PROBLEMS WITH 0 SIZE OR BLANK INPUT

    char *str= string;
    int slen = strlen(str); //string length
    int ctfor = 0; //counter forward
    int ctbak = 0; //counter back

    while(isspace((unsigned char)*str)){ str++; ctfor++; }; //count to start of word
    while(*str){str++;}; //go to end

    //unsigned char
    do{ str--; ctbak++; }while(isspace((unsigned char)*str)); //count from end to end of word

    int cbako = (slen - ctbak) + 1; //counter back reversed
    int wlen = cbako - ctfor; //get word length

    printf("\nstr_len:%d,counter_fore:%d,counter_bak:%d,cbakreversed:%d,wlen:%d",slen,ctfor,ctbak,cbako,wlen);  

    while(*str){ str--; }
    str++;

    while(isspace((unsigned char)*str)){
        str++; 
    }





    char newStr[wlen+1]; //char pointer gives segmentation fault
    memcpy(newStr,str,wlen); //not null terminated
    newStr[wlen] = '\0';

    printf("\n--%s--",newStr);

    //PASS POINTER TO POINTER for malloc to work / malloc inside another function
    *ptr = malloc(sizeof(newStr)+1); //memory


    strcat(*ptr,newStr);    
    printf("\nPTR is : %s",*ptr);


    printf("\n- leaving trimspaces function -");

}


int main(){
    addRecord("   ertsfs  ","  120,Dans st  ","   111 000 222");

}

【讨论】:

    【解决方案2】:

    无需将ptr 作为参数传递给trimspaces 调用。

    这有效(即使string 只是空格或空):

    char *trimspaces(char *string){
        size_t len = strlen(string);
        char *s = string; //start
        char *e = string + len - 1; //end
    
        while(s <= e && isspace(*s)) s++;
        while(e >= s && isspace(*e)) e--;
    
        size_t size = e - s + 1;
        char *ptr = (char*) malloc(size + 1);
    
        int i;
        for(i = 0; i < size; i++)
            ptr[i] = s[i];
        ptr[i] = '\0';
    
        return ptr;
    }
    

    如果您遇到指针越界的任何问题(我对此表示怀疑),请尝试使用索引而不是指针:

    char *trimspaces(char *string){
        int len = strlen(string);
        int s = 0; //start
        int e = len - 1; //end
    
        while(s <= e && isspace(string[s])) s++;
        while(e >= s && isspace(string[e])) e--;
    
        int size = e - s + 1;
        char *ptr = (char *) malloc(size + 1);
    
        int i;
        for(i = 0; i < size; i++)
            ptr[i] = string[i + s];
        ptr[i] = '\0';
    
        return ptr;
    }
    

    【讨论】:

    • 空字符串失败。
    • 不要投malloc()
    • 在空字符串上执行e = string + len - 1,即e = string - 1。这具有未定义的行为。
    • ptr 参数未使用。
    • 错了。形成无效指针本身就是 UB。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 2021-07-14
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    相关资源
    最近更新 更多