2013-03-14 87 views
0

我遇到了sscanf的麻煩。要檢查它,我做了一個簡單的文件,所以當我編譯如下:sscanf與字符串的奇怪行爲

#include <stdio.h> 
main(){ 
    char *a; 
    /* */ 
    char *s = "GET /something HTTP/1.1\r\n"; 
    printf("sscanf: %d\n", sscanf(s, "GET %s HTTP", a)); 
    printf("a: %s\n", a); 
    /* */ 
    printf("sscan: %d\n", sscanf("GET /more HTTP/1.1\r\n", "GET %s HTTP", a)); 
    printf("a: %s\n", a); 
} 

我得到正確的輸出:

sscanf: 1 
a: /something 
sscan: 1 
a: /more 

但是當我評論空評論之間的線唱,我得到:

sscan: 0 
a: (null) 

問題1:怎麼會這樣?

,多一些:如果我寫char *a = NULL,我得到:

sscanf: 0 
a: (null) 
sscan: 0 
a: (null) 

問題2:爲什麼呢?

+2

你還沒有爲'a'分配內存,所以'sscanf'是未定義的行爲。爲什麼它假裝在第一種情況下工作只能通過調查編譯器輸出來確定。 – 2013-03-14 15:57:40

+0

一些解釋:首先我有一個問題(Q2),當我檢查(Q2)時問題(Q1)出現了。這個問題不允許我使用選項'-Werror -Wall'沒有'#pragma GCC診斷...' – 2013-03-14 15:58:54

+0

@DanielFischer,謝謝,我讀過男人了! – 2013-03-14 16:01:44

回答

0

您正在將數據寫入未分配的空間。 char *a;只是一個指向隨機存儲器的指針。在嘗試將數據放入「字符串」中後,您會調用未定義的行爲,並可能發生任何事情。

2

您正在將未初始化的指針傳遞給sscanf。將char *a;更改爲char a[100],它應該可以正常工作。

+0

'man sscanf'說,有一個修飾符「%as」動態分配內存,但它不起作用。預先分配內存是件壞事,因爲它應該和我在其中搜索子字符串的緩衝區一樣多。 – 2013-03-14 16:14:56

5

您正在將字符串複製到未初始化的指針(a)。你需要爲它分配存儲空間(使用malloc),或者聲明一個數組。

當您不分配任何存儲時,實現有時可能會正常工作。當您將NULL分配給a時,sscanf未能存儲任何內容,因此您嘗試使用空指針(其中printf打印爲(null))打印「字符串」。在某些系統上,你的程序只會崩潰。

有一個編譯器/庫擴展允許自動分配字符串,但顯然這不是可移植的,並非所有的編譯器都支持它。

char *a; 
scanf("%ms", &a;) // allocates storage for a 

您可以將未初始化的指針傳遞給函數,但是注意&

+0

爲什麼這不在C99std中?似乎對我非常有用(特別是通過網絡接收信息)。這樣做的失敗是什麼? – zigo 2014-04-24 16:16:27

0

嗯,在我的情況下,唯一正確的事情,因爲我認爲,應該是這樣:

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

main(){ 
    char *s = strdup("GET /something HTTP/1.1\r\n"); 
    char *a, *e, *ans; 
    char *end = s + strlen(s); 
    a = strstr(s, "GET"); 
    if(!a) return -1; 
    a += 4; 
    if(a >= end) return -1; 
    e = strstr(a, "HTTP/1.1"); 
    if(!e) return -1; 
    *(--e) = 0; 
    ans = strdup(a); 
    printf("ans: %s\n", ans); 
} 

在通常情況下串s可以有一個非常大的尺寸,所以這將是最好不要分配太大記憶,但按照我的需要分配權利。

帶「%as」的情況不適用於我的gcc(4.7.2)。

+1

你可以用'm'代替 - 我已經在我的答案中加入了一個例子。 – teppic 2013-03-14 16:33:41

+0

它沒有工作。現在我試試看:如果你說'sscanf(「GET more here」,「GET%ms」,&x);'It works!但是第一次我忘記了&符號並得到了錯誤的結果 – 2013-03-14 17:14:37

+0

是的 - 那是因爲sscanf '需要改變指向新內存的指針,所以它需要'&'。 – teppic 2013-03-14 17:18:25