討論區快速選單
知識庫快速選單
軟體開發過程中有哪些資安漏洞? 傑米的攝影旅遊筆記 網路投保旅行平安險
[ 回上頁 ] [ 討論區發言規則 ]
scanf以16進制讀入字串陣列為何僅能讀入4筆資料?
更改我的閱讀文章字型大小
作者 : phoebus7(小P) 貼文超過200則人氣指數超過30000點
[ 貼文 407 | 人氣 43340 | 評價 690 | 評價/貼文 1.7 | 送出評價 121 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/5 下午 11:20:56
部分code如下,我想要輸入一筆16進位的字串,並且將其印出來 但為何僅能顯示4筆資料呢?

int main(){
    int i = 0;
    char b[100];
    scanf("%x",&b);
    while(i < strlen(b))
    {
     printf("%c",i,b[i]);
     i++;
    }
    system("pause");
    return 0;
}

例如:
輸入:6162636465
顯示:edcb

另外我還有一個問題就是為何顯示時順序是相反的,而不是abcde呢?
作者 : phoebus7(小P) 貼文超過200則人氣指數超過30000點
[ 貼文 407 | 人氣 43340 | 評價 690 | 評價/貼文 1.7 | 送出評價 121 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/5 下午 11:25:31
修正一下:
     printf("%c",b[i]);
作者 : cromayen2000(CROMAYEN2000) OpenGL卓越專家貼文超過500則人氣指數超過10000點
[ 貼文 646 | 人氣 22308 | 評價 2260 | 評價/貼文 3.5 | 送出評價 38 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/6 下午 10:26:48
>部分code如下,我想要輸入一筆16進位的字串,並且將其印出來 但為何僅能顯示4筆資料呢?
>int main(){
> int i = 0;
> char b[100];
> scanf('%x',&b);
> while(i < strlen(b))
> {
> printf('%c',i,b[i]);
> i++;
> }
> system('pause');
> return 0;
>}
>
>例如:
>輸入:6162636465
>顯示:edcb
>
>另外我還有一個問題就是為何顯示時順序是相反的,而不是abcde呢?

因為你程式寫錯了 如果你要輸入的是一個 16 進制的字串
> scanf('%x',&b);
1.字串是沒有區分 16 進制 而且字串其實是字元的陣列本身就已經是一個記憶體位址了 所以因該寫作
所以因該是 scanf("%s", b);

2. 顯示的時候直接輸出字串就可以了
printf("%s", b);
作者 : phoebus7(小P) 貼文超過200則人氣指數超過30000點
[ 貼文 407 | 人氣 43340 | 評價 690 | 評價/貼文 1.7 | 送出評價 121 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/7 下午 07:14:09
>因為你程式寫錯了 如果你要輸入的是一個 16 進制的字串
>> scanf('%x',&b);
喔喔不好意思沒注意到~不小心加了&
>1.字串是沒有區分 16 進制 而且字串其實是字元的陣列本身就已經是一個記憶體位址了 所以因該寫作
>所以因該是 scanf('%s', b);
可是為什麼使用
scanf("%x",b);
再使用
printf("%s",b);
印出時,卻可以達到轉換的效果呢?
而按照您說的方法卻無法達到我想要的轉換效果<輸入16進位,輸出為轉換的結果>
作者 : foxyboss(FOXYBOSS)
[ 貼文 5 | 人氣 0 | 評價 0 | 評價/貼文 0 | 送出評價 0 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/7 下午 07:29:42
麻煩小p 大大

可求助此問題??

http://www.programmer-club.com.tw/showsametitleN/cb/17127.html

謝謝
作者 : phoebus7(小P) 貼文超過200則人氣指數超過30000點
[ 貼文 407 | 人氣 43340 | 評價 690 | 評價/貼文 1.7 | 送出評價 121 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/7 下午 07:46:23
我想我大概知道原因在哪裡了,我使用scanf("%x",b)之所以只能讀到4個字元是因為只有一個%x
但是至於為何讀出來的結果卻是相反的還是不得其解

那想要做到將16進位的字串印出時轉換成字元,該如何達成呢?
因為沒辦法確定字串的長度,而且字串之間也不會有space<為連續字串>,該如何做讀取的動作才不會有問題?
作者 : kib72377(史努比) Visual Basic卓越專家Assembly優秀好手Access頂尖高手貼文超過1000則
[ 貼文 1455 | 人氣 1891 | 評價 8600 | 評價/貼文 5.91 | 送出評價 31 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人phoebus7註記此篇回應為很有道理 2010/11/7 下午 07:51:29

>可是為什麼使用
>scanf('%x',b);
這個只會轉成1個整數,
(你說的4筆資料應該是32位元,4個byte共8位數字)
>再使用
>printf('%s',b);
>印出時,卻可以達到轉換的效果呢?
>而按照您說的方法卻無法達到我想要的轉換效果<輸入16進位,輸出為轉換的結果>

而你要的數字,遠大於1個整數的size,因此得不到預期結果,
所以還是用文字型態去取得輸入,再自己做轉換才行得通.
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2189 | 人氣 89850 | 評價 10120 | 評價/貼文 4.62 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人phoebus7註記此篇回應為最佳解答 2010/11/7 下午 09:55:21
> 部分code如下,我想要輸入一筆16進位的字串,並且將其印出來 但為何僅能顯示4筆資料呢?
> ...
> 例如:
> 輸入:6162636465
> 顯示:edcb
>
> 另外我還有一個問題就是為何顯示時順序是相反的,而不是abcde呢?

你的問題本身有問題呢, 想想看, 16進位 輸入, 16進位 輸出, 這麼
輸入 即是 輸出 呀, 用你的例子, 如何輸入是 6162636465, 輸出
就 必 定 是 6162636465. 當中並不需轉換.

我估, 你想要的應該是 十進制輸入, 十六進制輸出吧, 如何是這樣,
這樣寫就可以了...
  int x;
  scanf("%i",&x);
  printf("%X\n",x);

當然, 你的例子, 輸入的範圍超過了 32 bit 整數範圍, 這麼用 64 bit 吧, 即...
  __int64 x;
  scanf("%I64i", &x);
  printf("%I64X\n", x);
這樣, 輸入/輸出 就會是
輸入:6162636465
顯示:16F525EB1

至於把 整數 強制轉型成 字串後, "為什麼 字串內容會有字母 呢?", 這個問題嘛...
這只是巧合, 並沒什麼特別含意.
作者 : phoebus7(小P) 貼文超過200則人氣指數超過30000點
[ 貼文 407 | 人氣 43340 | 評價 690 | 評價/貼文 1.7 | 送出評價 121 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/8 上午 12:58:49
>你的問題本身有問題呢, 想想看, 16進位 輸入, 16進位 輸出, 這麼
>輸入 即是 輸出 呀, 用你的例子, 如何輸入是 6162636465, 輸出
>就 必 定 是 6162636465. 當中並不需轉換.
啊啊抱歉,表達不清楚= =
>我估, 你想要的應該是 十進制輸入, 十六進制輸出吧, 如何是這樣,
嗯,沒錯 其實我的意思就是這樣~
原本是打算輸入一段字串並且將其轉成16進位之後寫入到txt裡頭
之後再從txt讀取出來並且還原回去.
感謝以上諸位的解答囉~
作者 : ziyuefan(紫曰)
[ 貼文 160 | 人氣 375 | 評價 800 | 評價/貼文 5 | 送出評價 7 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人phoebus7註記此篇回應為很有道理 2010/11/8 下午 09:24:25
C語法不熟

首先 先不管字串情形
只單就對一個字元來看
一個字元就是1byte = 00h~ffh = 0d~255d

那要轉換成16進位就是要連除取商數與餘數

怎麼取?

當然就是除以16 取商數與餘數

high_nibble = v \ 16 ; low_nibble = v % 16

也有另一取法 使用遮罩跟移位

high_nibble = (v & 0xf0) >> 4
low_nibble = (v & 0x0f)

取得nibble 後 再用查表法(TABLE ACCESS)

hex_table = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
printf("%c",hex_table[high_nibble]);
printf("%c",low_table[high_nibble]);


至於從16進位字串原則是要一次取兩個byte 回來

第一個byte 當成HIGH NIBBLE 處理
第二個byte 當成LOW nibble 處理
課題是如何把
字元 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
轉換城
數值 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
也可以說
如何把
字元 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46
轉換城
數值 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15

方法1:可以用查表來查回 (C應該有搜尋函數) 傳回的位置應該就是取得的數值
方法2: 可以用連續計算(配合邏輯) newvalue = v - 0x30 - ((v >= 0x41) * 0x11)
     (這是假定true=1, false=0 的情況, 可攜性比較低)

找回數值後 第一個數值就乘以16 或左移(<<) 4bit 之後再加上第二個數值 或用 & 來組合回來

newvalue = (v1 << 4) and v2
newvalue = v1 * 16 + v2

還原回來就是ascii code 了 所以可以直接顯示
printf("%c",newvalue);



P.S. nibble 就是4bit 16進位 也就是 0-F

回的離題了 抱歉
作者 : sflam(Raymond)討論區板主 Visual C++ .NET卓越專家VC++一代宗師新手入門優秀好手資訊類作業求救頂尖高手C++一代宗師貼文超過4000則
[ 貼文 4945 | 人氣 9172 | 評價 32290 | 評價/貼文 6.53 | 送出評價 142 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人phoebus7註記此篇回應為最佳解答 2010/11/8 下午 11:23:49
>原本是打算輸入一段字串並且將其轉成16進位之後寫入到txt裡頭
>之後再從txt讀取出來並且還原回去.
>感謝以上諸位的解答囉~

首先要理解兩點:

1. 所有格式化輸入 [f]scanf() 都是讀入字元, 然後轉換成格式字串內 (scanf() 的第一個 format specification 參數) 所要求的格式, 並存入相關的參數內.

如: scanf("%x", &i);
scanf() 會逐字元的檢查, 看是不是合格的 16 進制的字元符號 ('0'~'9', 'a'~'f', 'A'~'F') 之一. 如果是就把它們轉換成相應的數值, 並存放入 'i'. 只要某個字元不是合格符號之一, 就結束運作返回.

(如果格式字串內的格式和相關的參數類型不符, 就會導致不可預期的結果.)


2. 所有的數值都是以 2 進制的方式來儲存的. 「N 進制」對數值本身來說沒有意義. 10, 0xA, 012 (八進制), 或是 1010b (二進制) 都是同樣的數值, 你可以用任何一種來表示正常人手指頭的數目.

反過來說, 一組數字字串本身也是沒有意義的, 如果你不知道這組數字是以什麼進制來表示的, 你根本無法知道數值的大小.

所以, 數字必須要配合 base 才有意義. 這就是 scanf() 及 printf() 都有以用什麼 base 來讀取及輸出的格式的原因. C 語言標準支援 3 種數值的輸入/輸出格式 "%o", "%d", 及 "%x", 分別代表 8, 10 及 16 進制的 base.

scanf() 用 "%o", "%d", 或 "%x" 的格式來讀 "1000" 會得到三個不同的數值. 同樣的, 用 "%o", "%d", 或 "%x" 來打印 1000 這個數值也會得到不同的輸出.


綜合以上兩點, 一旦你以某進制的格式成功的讀入數值後, 「轉換成 N 進制」是沒有意義的. 「轉換」只有在以格式化形式做輸出時才有意義, 它的意義是表現在「以 N 進制的格式來打印該數值」. 如果你是用標準的 "%o", "%d" 或 "%x" 來輸入/輸出, 「轉換」已經自動的在 scanf() 及 printf() 裡給你做好了.

在兩個情況下, 你才要自己寫轉換的邏輯:
- 你需要的不是標準支援的進制格式, 比方說 2 進制.
- 需要的數值大小超出內建數值類型的範圍, 比方說 256 位元.

當然, 如果是第二個原因, 你所要做的就不止是轉換的邏輯了.


〔回到你的問題〕
如果你要的是 十進制輸入, 十六進制輸出, 而數值的大小是在 int 的範圍內, 你也不需要寫任何轉換的邏輯, 因為 printf()/scanf() 內部已經幫你做轉換了:

  int i;
  scanf("%d", &i); // 十進制輸入
  fprintf(..., "%x\n", i); // 十六進制輸出至文字檔
  ...
  fscanf(..., "%x", &i); // 十六進制自文字檔讀入
  printf("%d", i); // 以十進制的格式來輸出


作者 : phoebus7(小P) 貼文超過200則人氣指數超過30000點
[ 貼文 407 | 人氣 43340 | 評價 690 | 評價/貼文 1.7 | 送出評價 121 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2010/11/9 上午 02:42:30
ziyuefan大的解析以我的能力實在是有點難以完全理解啊~^ ^
不過還是很感謝花時間解說~

sflam大的解釋實在是很詳細,雖然大致上的原理我略懂(%o,%x...等),但是還是不夠熟捻,十分感謝您如此完整的解答^ ^
 板主 : simula
 > C++ - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - C++ - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
C++
1 Raymond 13050 
2 青衫 4760 
3 simula 4690 
4 coco 4030 
5 白老鼠(Gary) 3670 
6 ozzy 2540 
7 Ben 2250 
8 Anderson 1960 
9 windblown 1650 
10 Kenny 1560 
C++
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2019 程式設計俱樂部 http://www.programmer-club.com.tw/
0.1875