C语言关于fscanf的问题

培根0327 2014-06-26 12:16:31
目前只学过C和JAVA,然后这学期有个工程实践是让用任何一种语言写DES算法的加密解密。考虑到JAVA学的不怎么好,然后在晚上看到说C在这种数的运算上要更快,所以就用C写的DES加密解密。

最初写的解密算法需要输入密文(64bit),考虑到输入的数据太长,所以想改用文件。

现在写成的结果就是,将加密好的密文通过fprintf写入到 in.text 文件中。解密的时候用fscanf从 in.text 文件中直接读取,然后解密。

一开始我写的是 fprintf(fp1,"%d",output[i]); 发现可以将数据写入到文件中,但如果使用 fscanf(fp1,"%d",&ctext[i]); 读取数据,则数据读取不到。

但如果将两个都改成 fprintf(fp1,"%d\n",output[i]); 和 fscanf(fp1,"%d\n",&ctext[i]); 则写入文件和读取文件都是正常的。

所以,为什么加了一个换行符就正确了?

另外,如果有个for循环,每次fscanf读取两个字符,例如fscanf(fp1,"%d\n%d\n",&a,&b); 然后读取的文件里的数据是1\n2\n3\n4\n,那么第一次读取是读取的1 2 第二次就是读取3 4吗?

再另外,关于DES算法实现的一个问题,听说DES算法的好代码都是用 布尔型 的数组保存的二进制数,记得同学说的貌似是因为布尔型运算快一些。这是为什么呢?对于布尔型懂得不多。有了解的人麻烦大体讲一下吧。

谢谢各位了。
...全文
287 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
707wk 2014-06-27
  • 打赏
  • 举报
回复
自己动手写一些测试代码,不就能解决这些问题了吗
longburulin 2014-06-27
  • 打赏
  • 举报
回复
当然会后移了 为何这样自己能测试的 可以看到结果的东西为什么自己不操作一下,自己多操作比多问更好吧
赵4老师 2014-06-27
  • 打赏
  • 举报
回复
Format Specification Fields: scanf and wscanf Functions A format specification has the following form: %
  • [width] [{h | l | I64 | L}]type The format argument specifies the interpretation of the input and can contain one or more of the following: White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input. Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates. Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list. The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read. When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string. An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification. Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number. The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%. An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.
赵4老师 2014-06-26
  • 打赏
  • 举报
回复
仅供参考
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "advapi32.lib")
#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH  0x00800000
void HandleError(char *s);
//--------------------------------------------------------------------
//  These additional #define statements are required.
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
//   Declare the function EncryptFile. The function definition
//   follows main.
BOOL EncryptFile(
    PCHAR szSource,
    PCHAR szDestination,
    PCHAR szPassword);
//--------------------------------------------------------------------
//   Begin main.
void main(void) {
    CHAR szSource[100];
    CHAR szDestination[100];
    CHAR szPassword[100];
    printf("Encrypt a file. \n\n");
    printf("Enter the name of the file to be encrypted: ");
    scanf("%s",szSource);
    printf("Enter the name of the output file: ");
    scanf("%s",szDestination);
    printf("Enter the password:");
    scanf("%s",szPassword);
    //--------------------------------------------------------------------
    // Call EncryptFile to do the actual encryption.
    if(EncryptFile(szSource, szDestination, szPassword)) {
        printf("Encryption of the file %s was a success. \n", szSource);
        printf("The encrypted data is in file %s.\n",szDestination);
    } else {
        HandleError("Error encrypting file!");
    }
} // End of main
//--------------------------------------------------------------------
//   Code for the function EncryptFile called by main.
static BOOL EncryptFile(
    PCHAR szSource,
    PCHAR szDestination,
    PCHAR szPassword)
//--------------------------------------------------------------------
//   Parameters passed are:
//     szSource, the name of the input, a plaintext file.
//     szDestination, the name of the output, an encrypted file to be
//         created.
//     szPassword, the password.
{
    //--------------------------------------------------------------------
    //   Declare and initialize local variables.
    FILE *hSource;
    FILE *hDestination;
    HCRYPTPROV hCryptProv;
    HCRYPTKEY hKey;
    HCRYPTHASH hHash;
    PBYTE pbBuffer;
    DWORD dwBlockLen;
    DWORD dwBufferLen;
    DWORD dwCount;
    //--------------------------------------------------------------------
    // Open source file.
    if(hSource = fopen(szSource,"rb")) {
        printf("The source plaintext file, %s, is open. \n", szSource);
    } else {
        HandleError("Error opening source plaintext file!");
    }
    //--------------------------------------------------------------------
    // Open destination file.
    if(hDestination = fopen(szDestination,"wb")) {
        printf("Destination file %s is open. \n", szDestination);
    } else {
        HandleError("Error opening destination ciphertext file!");
    }
    //以下获得一个CSP句柄
    if(CryptAcquireContext(
                &hCryptProv,
                NULL,               //NULL表示使用默认密钥容器,默认密钥容器名
                //为用户登陆名
                NULL,
                PROV_RSA_FULL,
                0)) {
        printf("A cryptographic provider has been acquired. \n");
    } else {
        if(CryptAcquireContext(
                    &hCryptProv,
                    NULL,
                    NULL,
                    PROV_RSA_FULL,
                    CRYPT_NEWKEYSET))//创建密钥容器
        {
            //创建密钥容器成功,并得到CSP句柄
            printf("A new key container has been created.\n");
        } else {
            HandleError("Could not create a new key container.\n");
        }
    }
    //--------------------------------------------------------------------
    // 创建一个会话密钥(session key)
    // 会话密钥也叫对称密钥,用于对称加密算法。
    // (注: 一个Session是指从调用函数CryptAcquireContext到调用函数
    //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程)
    //--------------------------------------------------------------------
    // Create a hash object.
    if(CryptCreateHash(
                hCryptProv,
                CALG_MD5,
                0,
                0,
                &hHash)) {
        printf("A hash object has been created. \n");
    } else {
        HandleError("Error during CryptCreateHash!\n");
    }
    //--------------------------------------------------------------------
    // 用输入的密码产生一个散列
    if(CryptHashData(
                hHash,
                (BYTE *)szPassword,
                strlen(szPassword),
                0)) {
        printf("The password has been added to the hash. \n");
    } else {
        HandleError("Error during CryptHashData. \n");
    }
    //--------------------------------------------------------------------
    // 通过散列生成会话密钥
    if(CryptDeriveKey(
                hCryptProv,
                ENCRYPT_ALGORITHM,
                hHash,
                KEYLENGTH,
                &hKey)) {
        printf("An encryption key is derived from the password hash. \n");
    } else {
        HandleError("Error during CryptDeriveKey!\n");
    }
    //--------------------------------------------------------------------
    // Destroy the hash object.
    CryptDestroyHash(hHash);
    hHash = NULL;
    //--------------------------------------------------------------------
    //  The session key is now ready.
    //--------------------------------------------------------------------
    // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
    // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
    // 数据长度。
    dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
    //--------------------------------------------------------------------
    // Determine the block size. If a block cipher is used,
    // it must have room for an extra block.
    if(ENCRYPT_BLOCK_SIZE > 1)
        dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
    else
        dwBufferLen = dwBlockLen;
    //--------------------------------------------------------------------
    // Allocate memory.
    if(pbBuffer = (BYTE *)malloc(dwBufferLen)) {
        printf("Memory has been allocated for the buffer. \n");
    } else {
        HandleError("Out of memory. \n");
    }
    //--------------------------------------------------------------------
    // In a do loop, encrypt the source file and write to the source file.
    do {
        //--------------------------------------------------------------------
        // Read up to dwBlockLen bytes from the source file.
        dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
        if(ferror(hSource)) {
            HandleError("Error reading plaintext!\n");
        }
        //--------------------------------------------------------------------
        // 加密数据
        if(!CryptEncrypt(
                    hKey,           //密钥
                    0,              //如果数据同时进行散列和加密,这里传入一个
                    //散列对象
                    feof(hSource),  //如果是最后一个被加密的块,输入TRUE.如果不是输.
                    //入FALSE这里通过判断是否到文件尾来决定是否为
                    //最后一块。
                    0,              //保留
                    pbBuffer,       //输入被加密数据,输出加密后的数据
                    &dwCount,       //输入被加密数据实际长度,输出加密后数据长度
                    dwBufferLen))   //pbBuffer的大小。
        {
            HandleError("Error during CryptEncrypt. \n");
        }
        //--------------------------------------------------------------------
        // Write data to the destination file.
        fwrite(pbBuffer, 1, dwCount, hDestination);
        if(ferror(hDestination)) {
            HandleError("Error writing ciphertext.");
        }
    } while(!feof(hSource));
    //--------------------------------------------------------------------
    //  End the do loop when the last block of the source file has been
    //  read, encrypted, and written to the destination file.
    //--------------------------------------------------------------------
    // Close files.
    if(hSource)
        fclose(hSource);
    if(hDestination)
        fclose(hDestination);
    //--------------------------------------------------------------------
    // Free memory.
    if(pbBuffer)
        free(pbBuffer);
    //--------------------------------------------------------------------
    // Destroy session key.
    if(hKey)
        CryptDestroyKey(hKey);
    //--------------------------------------------------------------------
    // Destroy hash object.
    if(hHash)
        CryptDestroyHash(hHash);
    //--------------------------------------------------------------------
    // Release provider handle.
    if(hCryptProv)
        CryptReleaseContext(hCryptProv, 0);
    return(TRUE);
} // End of Encryptfile
//--------------------------------------------------------------------
//  This example uses the function HandleError, a simple error
//  handling function, to print an error message to the standard error
//  (stderr) file and exit the program.
//  For most applications, replace this function with one
//  that does more extensive error reporting.
void HandleError(char *s) {
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr, "Error number %x.\n", GetLastError());
    fprintf(stderr, "Program terminating. \n");
    exit(1);
} // End of HandleError

longburulin 2014-06-26
  • 打赏
  • 举报
回复
一开始我写的是 fprintf(fp1,"%d",output[i]); 发现可以将数据写入到文件中,但如果使用 fscanf(fp1,"%d",&ctext[i]); 读取数据,则数据读取不到。 比如你写入1到9的值 文本中存入为123456789,试问一下如果你写入的太多 怎么用fscanf读到数据呢?说白了就是你没有存入数据的个数 若你加入了换行或者空格等等能识别的符号 当然不包括数字 比如fprintf(fp1,"%d ",output[i])再用fscanf(fp1,"%d ",&ctext[i])也能正确读到你存入的数据 这样也就解决你第二问的问题了 至于用bool类型能快一些,个人认为快不了多少(甚至不会快,可能是多此一举吧,个人意见),虽然DES算法中用到的与或等操作多,但试想一下 比如3和8求或操作 他们在计算机中存入的方法本来就是2进制,你用bool类型也是2进制,这样就没有加快你的算法等等,如果想加快 还是建议从算法上改进吧
培根0327 2014-06-26
  • 打赏
  • 举报
回复
引用 1 楼 longburulin 的回复:
一开始我写的是 fprintf(fp1,"%d",output[i]); 发现可以将数据写入到文件中,但如果使用 fscanf(fp1,"%d",&ctext[i]); 读取数据,则数据读取不到。 比如你写入1到9的值 文本中存入为123456789,试问一下如果你写入的太多 怎么用fscanf读到数据呢?说白了就是你没有存入数据的个数 若你加入了换行或者空格等等能识别的符号 当然不包括数字 比如fprintf(fp1,"%d ",output[i])再用fscanf(fp1,"%d ",&ctext[i])也能正确读到你存入的数据 这样也就解决你第二问的问题了 至于用bool类型能快一些,个人认为快不了多少(甚至不会快,可能是多此一举吧,个人意见),虽然DES算法中用到的与或等操作多,但试想一下 比如3和8求或操作 他们在计算机中存入的方法本来就是2进制,你用bool类型也是2进制,这样就没有加快你的算法等等,如果想加快 还是建议从算法上改进吧
关于第一个问题我大概明白了。意思就是 假设我输入的是1 2 3 三个十进制,如果在写入文件的时候不加换行或者空格之类的,读取的时候会把1 2 3 当做一个字符读取是吗? 第二个问题我其实想问的是,如果第一次读取了前两个字符,再一次读取的时候文件指针就会往后移动两个,然后读取第三和第四个字符。是这样吗

70,022

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧