替换C char字符串中的字符串(strreplace,no sprintf)

时间:2018-01-21 11:05:32

标签: c string malloc realloc strncpy

对不起,如果这个问题已经得到解答(以我希望的方式:-)),我很抱歉,但我认为我有记忆问题。
假设有以下C函数(是的,这个非常脏并且没有优化):

public class Main2Activity extends AppCompatActivity {

public TextView ttkalorisehari, ttkaloriseminggu,txtbb;
double naik_bb,kcptjalan,hasil_bakar,durasi;
Spinner kcpt;
String[]kecepatan = {"...","Jalan kaki santai (3 mph)","Jalan kaki cepat (4-5 mph)","Jalan kaki menaiki bukit (3,5 mph)","Naik tangga (3 mph)","Jalan kaki turun bukit (2,5 mph)"};
ArrayAdapter<String> adapter;
EditText etbb,etdurasi;
Button bhitung;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);

    bhitung = (Button)findViewById(R.id.btnhitung);
    etbb = (EditText)findViewById(R.id.tbb);
    etdurasi = (EditText)findViewById(R.id.tdurasi);


    adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,kecepatan);
    kcpt.setAdapter(adapter);
    try {
        double nilai_bb = Double.parseDouble(ttkaloriseminggu.getText().toString());
        DecimalFormat df = new DecimalFormat("#.##");
        naik_bb = (Double.valueOf(nilai_bb)/7000);
        txtbb.setText(df.format(naik_bb));
    }catch (Exception e){
        Toast.makeText(getApplicationContext(),"Isi kolom kosong",Toast.LENGTH_LONG).show();
    }

    bhitung.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                pembakaran_kalori();
            }catch (Exception e){
                Toast.makeText(getApplicationContext(),"Kesalahan 2 : "+e.getMessage(),Toast.LENGTH_SHORT).show();
            }
        }
    });
}

public void pembakaran_kalori(){
    try {
        if (Integer.valueOf(etbb.getText().toString())>=54 && Integer.valueOf(etbb.getText().toString())<=63 ){
            kcpt.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                    switch (position){
                        case 1:
                            kcptjalan = 0.3;
                            break;
                        case 2:
                            kcptjalan = 0.16;
                            break;
                        case 3:
                            kcptjalan = 0.17;
                            break;
                        case 4:
                            kcptjalan = 0.12;
                            break;
                        case 5:
                            kcptjalan = 0.37;
                            break;
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
        }else if (Integer.valueOf(etbb.getText().toString())>=72 && Integer.valueOf(etbb.getText().toString())<=81 ){

            kcpt.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                    switch (position){
                        case 1:
                            kcptjalan = 0.23;
                            break;
                        case 2:
                            kcptjalan = 0.12;
                            break;
                        case 3:
                            kcptjalan = 0.13;
                            break;
                        case 4:
                            kcptjalan = 0.13;
                            break;
                        case 5:
                            kcptjalan = 0.27;
                            break;
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
        }
    }catch (Exception e){
        Toast.makeText(getApplicationContext(),"Kesalahan "+e.getMessage(),Toast.LENGTH_SHORT).show();
    }
    try {
        durasi = Double.parseDouble(etdurasi.getText().toString());
        hasil_bakar = ((durasi*kcptjalan)*2);
        Toast.makeText(getApplicationContext(),"Pembakaran kalori anda = "+kcptjalan,Toast.LENGTH_SHORT).show();
    }catch (Exception e){
        Toast.makeText(getApplicationContext(),"Kesalahan 3 : "+e.getMessage(),Toast.LENGTH_SHORT).show();
    }
}
   }

如图所示,它应该char *strreplace(char **str, char *dst, char *replace) { int replacestart = stringcompare(*str, dst), replaceend = strlen(dst), replacelen = strlen(replace); char *tmp1 = (char *)malloc(sizeof(char) * (replacestart + 1)), *tmp2 = (char *)malloc(sizeof(char) * ((strlen(*str) - replaceend) + 1)); memset(tmp1, 0, sizeof(char) * (replacestart + 1)); memset(tmp2, 0, sizeof(char) * ((strlen(*str) - replaceend) + 1)); strncpy(tmp1, *str, replacestart); strncpy(tmp2, *str + replacestart + replaceend, (strlen(*str) - (replaceend + replacestart))); *str = realloc(*str, strlen(tmp1) + replacelen + strlen(tmp2)); memset(*str, 0, strlen(tmp1) + replacelen + strlen(tmp2)); strncpy(*str, tmp1, strlen(tmp1)); strncpy(*str + strlen(tmp1), replace, replacelen); strncpy(*str + strlen(tmp1) + replacelen, tmp2, strlen(tmp2)); return *str; } 取代*dst whithin *replace。 这基本上按预期工作。这就是问题所在:

输出(**str)在设置后不会被零清除,并且即使在重新分配后仍然有错误的长度。
意思是,如果替换后字符串更长,则最后一个字符被切割为*str 反过来,如果字符串更短,则找到字符串末尾的旧字符。

我错了什么。提到我不想使用*str而不使用C ++ - STL,只想用C中的指针来做这个。

换句话说,用指针替换c char字符串中的字符串是正确的方法。

非常感谢。

在获取更多信息之后编辑

我使用此功能如下:

sprintf

编辑2,添加...open a textfile via FILE type, determining file lengts (fseek)... char *filecontent = (char *)malloc(sizeof(char) * filesize); if(filesize != fread(filecontent, sizeof(char), filesize, fd)) { free(filecontent); return -1; } streplace(&filecontent, "[#TOBEREPLACED#]", "replaced"); ...doing other stuff with filecontent...

stringcompare()

2 个答案:

答案 0 :(得分:1)

您的功能看起来过于复杂。这是一个简单的工作版本:

char *strreplace(char **str, char *dst, char *replace)  char *strreplace(char **str, char *dst, char *replace)
{
    char *start, *tmp;
    int n;
    if ((start=strstr(*str,dst))==0) return(0);
    n= (start-*str) + strlen(start+strlen(dst)) + strlen(replace) + 1;
    tmp=malloc(n);
    strncpy(tmp,*str,start-*str);
    strcpy(tmp+(start-*str),replace);
    strcat(tmp,start+strlen(dst));
    free(*str);
    *str= tmp;
    return(tmp);
}

使用测试功能:

void reptest(void)
{
    char *src;
    char rep[]= "brave new world";
    src=malloc(strlen("Hello world of wonders")+1);
    strcpy(src,"Hello world of wonders");
    strreplace(&src,"world",rep);
    printf("%s\n", src);
    free(src);
}

编辑:我以前的版本忘了复制其余部分。固定的。

答案 1 :(得分:1)

该功能的逻辑并不像第一眼看上去那么简单。

如果源字符串为空,则应确定要执行的操作1)2)如果目标字符串为空。

例如,如果目标字符串为空,则标准函数strstr将返回源字符串的第一个字符的地址。但是逻辑上如果dst是一个空字符串,那么源字符串不应该被更改,除非它是一个空字符串。在这种情况下,函数应该只创建一个等于字符串replace的新字符串。

考虑到因为字符dstreplace未在函数中更改,因此应使用限定符const声明它们。

char * strreplace( char **str, const char *dst, const char *replace );

此函数还应通过在分配失败时返回空指针来报告函数内的新内存分配是否成功。

考虑到所有这些因素,该功能可以按照以下方式进行,如演示程序中所示。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * strreplace( char **str, const char *dst, const char *replace )
{
    char *result = *str;

    if ( *str[0] == '\0' )
    {
        if ( dst[0] == '\0' && replace[0] != '\0' )
        {
            char *result = malloc( strlen( replace ) + 1 );

            if ( result )
            {
                strcpy( result, replace );
                free( *str );
                *str = result;
            }
        }
    }
    else if ( dst[0] != '\0' )
    {
        char *pos = strstr( *str, dst );

        if ( pos != NULL )
        {
            size_t dst_n = strlen( dst );
            size_t replace_n = strlen( replace );

            result = ( char * )malloc( strlen( *str ) - dst_n + replace_n + 1 );

            if ( result )
            {
                size_t n = pos - *str;

                strncpy( result, *str, n );
                strcpy( result + n, replace );
                strcpy( result + n + replace_n, *str + n + dst_n );
            }

            free( *str );
            *str = result;
        }
    }


    return result;
}

int main(void) 
{
    const char *hello = "Hello everybody here";
    char *str = malloc( sizeof( char ) );
    str[0] = '\0';

    if ( strreplace( &str, "", hello ) )
    {
        puts( str );
    }

    if ( strreplace( &str, "everybody", "Eurobertics" ) )
    {
        puts( str );
    }

    if ( strreplace( &str, "Hello", "Bye" ) )
    {
        puts( str );
    }

    if ( strreplace( &str, " here", "" ) )
    {
        puts( str );
    }

    if ( strreplace( &str, "Bye ", "" ) )
    {
        puts( str );
    }

    free( str );

    return 0;
}

程序输出

Hello everybody here
Hello Eurobertics here
Bye Eurobertics here
Bye Eurobertics
Eurobertics
相关问题