我已经编写了这段代码来获取学生的Letter成绩并计算他们的GPA。 当我运行该程序时,我可以正确获得学生的姓名和科目,但我无法获得成绩或GPA。
示例输入:
//
// The original Delphi code is : XMLHookUnit.pas released 2015.09.20
// Last version: 0.1 released 2015.09.20
// The initial developer is Cedomir Plavljanic (cedomir.plavljanic@yahoo.com)
// Copyright (C) 2015-2015 Cedomir Plavljanic
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version
//
// This unit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// This unit hooking 2 methods from XMLDoc.TXMLNode and 1 method from XMLDoc.TXMLNodeList
// Allows use of units created with XML binding wizard with multiple namespace
//
// This is only test
//
// XML Binding Wizard
// - change all the names that end with _ (All signature nodes have this problem)
// - example: TSignatureType_ -> TSignatureType_ds
//
// Usage: add the unit to project
//
// This unit contains variables
// - ListNameSpace - dictionary for pair prefixes and namespace
// - in example pair is from XML Schema Definition in UBL 2.1 by Oasis
// http://docs.oasis-open.org/ubl/os-UBL-2.1/UBL-2.1.html
// - for own use must changed
// - DigitalSignatureWithoutPrefix - flag for add or remove digital signature prefix in nodename
//
//
// This unit contains Helper: TXMLNodeListHelper, TXMLNodeHelper
// This unit contains function for hooking TXMLNode and TXMLNodeList
// For hooking in testing using example from Hook Api Library 0.2 [Ring3] By Anskya Email:Anskya@Gmail.com
// - with litle modification in call function VirtualProtect
// - flNewProtect used as PAGE_READWRITE
//
// version: 0.1
// can be used with all versions of Delphi that have suport generic TDictionary
// for older versions of Delphi have to ask via e-mail or add support for TDictionary
// I also have a version for Delphi 2007 (XML binding wizard is bad, must be used from newer version of Delphi)
//
unit XMLHookUnit;
interface
uses
System.Generics.Collections;
var
////Dictionary for pair prefixes and namespaces in all *.xsd file (without default namespace)
ListNameSpace : TDictionary<String, String>;
//Include or Exclude ds: prefix in digital signature node
DigitalSignatureWithoutPrefix : Boolean = True;
//Hook 1 methods from TXMLNodeList and 2 method from TXMLNode
//TXMLNodeList.GetNode
//TXMLNode.RegisterChildNode
//TXMLNode.InternalAddChildNode
//for hooking in testing using example from Hook Api Library 0.2 [Ring3] By Anskya Email:Anskya@Gmail.com
//with litle modification in call function VirtualProtect
//flNewProtect is PAGE_READWRITE
procedure HookXMLNodeLibrary;
//UnHook 1 methods from TXMLNodeList and 2 method from TXMLNode
//TXMLNodeList.GetNode
//TXMLNode.RegisterChildNode
//TXMLNode.InternalAddChildNode
//for unhooking in testing using example from Hook Api Library 0.2 [Ring3] By Anskya Email:Anskya@Gmail.com
//with litle modification in call function VirtualProtect
//flNewProtect is PAGE_READWRITE
procedure UnHookXMLNodeLibrary;
implementation
uses
System.Types, StrUtils, Variants, HookApiLib, xmldom, XMLDoc, XMLIntf;
const
//namespace for digital signature
NameSpace_DigitalSignature = 'http://www.w3.org/2000/09/xmldsig#';
var
//Flag is True if methods from XMLDoc are hooked
IsHookXMLNodeLibrary : Boolean = False;
type
//access to proteted part in TXMLNodeList
TXMLNodeListHelp = class(TXMLNodeList);
//access to proteted part in TXMLNode
TXMLNodeHelp = class(TXMLNode);
//helper for TXMLNodelist
TXMLNodeListHelper = class helper for TXMLNodeList
public
//avoid overload trouble
//getnode call wrong findnode function
function FindNodeHelp(aField: DOMString):IXMLNode;
//find prefix for node in ListNameSpace
function FindPrefixHelp(aField:DOMString):String;
end;
//helper function for TXMLNodelist
TXMLNodeHelper = class helper for TXMLNode
public
//extract LocalName, Prefix and Namespace based on NodeName
procedure ExtractFieldPrefixNameSpace(const aNodeName: DOMString; out aField, aPrefix, aNameSpace: DOMString);
end;
//prototype for hooking TXMLNodeList.GetNode
TProtoTypeNodeListGetNode = function( const aSelf:TXMLNodeListHelp;
const IndexOrName: OleVariant): IXMLNode;
//prototype for hooking TXMLNode.RegisterChildNode
TProtoTypeNodeRegisterChildNode = procedure(const aSelf:TXMLNodeHelp;
const aField: DOMString;
const ChildNodeClass: TXMLNodeClass;
const aNameSpace : DOMString);
//prototype for hooking TXMLNode.InternalAddChild
TProtoTypeNodeInternalAddChild = function(const aSelf:TXMLNodeHelp;
const NodeClass: TXMLNodeClass;
const NodeName, NamespaceURI: DOMString;
const Index: Integer): IXMLNode;
var
//Save old address for TXMLNodeList.GetNode
SavePrototypeGetNode : TProtoTypeNodeListGetNode = nil;
//Save old address for TXMLNode.RegisterChildNode
SaveProtoTypeRegisterChildNode : TProtoTypeNodeRegisterChildNode = nil;
//Save old address for TXMLNode.InternalAddChild
SaveProtoTypeNodeInternalAddChild : TProtoTypeNodeInternalAddChild = nil;
{ TXMLNodeListHelper }
function TXMLNodeListHelper.FindNodeHelp(aField: DOMString): IXMLNode;
var
aPrefix: string;
begin
aPrefix := FindPrefixHelp(aField);
if aPrefix <> '' then Result := FindNode(aPrefix+':'+aField, '');
if Result = nil then Result := FindNode(aField, '');
end;
function TXMLNodeListHelper.FindPrefixHelp(aField: DOMString): String;
var
aNodeClass:TNodeClassArray;
i: Integer;
aTest:TPair<String,String>;
begin
Result := '';
aNodeClass := TXMLNodeHelp(Self.Owner).ChildNodeClasses;
aField:=ExtractLocalName(aField);
for i := 0 to Length(aNodeClass)-1 do
if aNodeClass[i].NodeName = aField then begin
for aTest in ListNameSpace do begin
if aTest.Value = aNodeClass[i].NamespaceURI then begin
Result := aTest.Key;
Break;
end;
end;
Break;
end;
end;
{ TXMLNodeHelper }
procedure TXMLNodeHelper.ExtractFieldPrefixNameSpace(const aNodeName : DOMString; out aField, aPrefix, aNameSpace: DOMString);
var
i: Integer;
sHelp:DOMString;
Test:TPair<String,String>;
Flag : Boolean;
begin
sHelp := ExtractLocalName(aNodeName);
aPrefix := '';
aNameSpace := '';
Flag := False;
for i := 0 to Length(ChildNodeClasses) - 1 do begin
if ChildNodeClasses[i].NodeName = sHelp then begin
aNameSpace := ChildNodeClasses[i].NamespaceURI;
for Test in ListNameSpace do begin
if Test.Value = aNameSpace then begin
aPrefix := Test.Key;
Flag := DigitalSignatureWithoutPrefix and (aNameSpace = NameSpace_DigitalSignature);
Break;
end;
end;
Break;
end;
end;
if (aPrefix = '') or (Flag) then begin
aField := ExtractLocalName(aNodeName);
if aNameSpace = '' then aNameSpace := GetNamespaceURI;
end else
aField := aPrefix + ':' + ExtractLocalName(aNodeName);
end;
//help function for find namaspase bassed on classname
//last part after underscore in classname is prefix
function GetNameSpace(const ChildNodeClass: TXMLNodeClass): DOMString;
var
aList : TStringDynArray;
begin
Result := ChildNodeClass.ClassName;
aList:=StrUtils.SplitString(Result,'_');
if Length(aList)>1 then
ListNameSpace.TryGetValue(aList[Length(aList)-1],Result)
else
Result := '';
end;
//replace for TXMLNodeList.GetNode
function GetNodeHelp( const aSelf:TXMLNodeListHelp;
const IndexOrName: OleVariant):IXMLNode;
begin
if VarIsOrdinal(IndexOrName) then
Result := SavePrototypeGetNode(aSelf,IndexOrName)
else begin
Result := aSelf.FindNodeHelp(DOMString(IndexOrName));
if Result = nil then
Result := SavePrototypeGetNode(aSelf,IndexOrName);
end;
end;
//replace for TXMLNode.RegisterChildNode
procedure RegisterChildNodeHelp(const aSelf:TXMLNodeHelp;
const aField: DOMString;
const ChildNodeClass: TXMLNodeClass;
const aNameSpace : DOMString);
var
hNameSpace: DOMString;
begin
if aNameSpace<>'' then
hNameSpace := aNameSpace
else begin
hNameSpace := GetNameSpace(ChildNodeClass);
if hNameSpace = '' then hNameSpace := aSelf.GetNamespaceURI;
end;
SaveProtoTypeRegisterChildNode(aSelf, aField, ChildNodeClass, hNameSpace);
end;
//replace for TXMLNode.InternalAddChild
function InternalAddChildHelp(const aSelf:TXMLNodeHelp;
const NodeClass: TXMLNodeClass;
const NodeName, NamespaceURI: DOMString;
const Index: Integer): IXMLNode;
var
aField, aPrefix, aNameSpace:DOMString;
begin
aSelf.ExtractFieldPrefixNameSpace(NodeName, aField, aPrefix, aNameSpace);
Result := SaveProtoTypeNodeInternalAddChild(aSelf, NodeClass, aField, aNameSpace, Index);
end;
procedure HookXMLNodeLibrary;
begin
if IsHookXMLNodeLibrary then Exit;
@SavePrototypeGetNode := HookCode(@TXMLNodeListHelp.GetNode, @GetNodeHelp);
@SaveProtoTypeRegisterChildNode := HookCode(@TXMLNodeHelp.RegisterChildNode, @RegisterChildNodeHelp);
@SaveProtoTypeNodeInternalAddChild := HookCode(@TXMLNodeHelp.InternalAddChild, @InternalAddChildHelp);
IsHookXMLNodeLibrary := True;
end;
procedure UnHookXMLNodeLibrary;
begin
if not IsHookXMLNodeLibrary then Exit;
UnHookCode(@SavePrototypeGetNode);
UnHookCode(@SaveProtoTypeRegisterChildNode);
UnHookCode(@SaveProtoTypeNodeInternalAddChild);
SavePrototypeGetNode := nil;
SaveProtoTypeRegisterChildNode := nil;
SaveProtoTypeNodeInternalAddChild := nil;
IsHookXMLNodeLibrary := False;
end;
//Dictionary for prefixes and namespaces
procedure AddNameSpace;
begin
ListNameSpace.Add('xsd','http://www.w3.org/2001/XMLSchema');
ListNameSpace.Add('cac','urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2');
ListNameSpace.Add('cbc','urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2');
ListNameSpace.Add('ccts','urn:un:unece:uncefact:documentation:2');
ListNameSpace.Add('ext','urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2');
ListNameSpace.Add('udt','urn:oasis:names:specification:ubl:schema:xsd:UnqualifiedDataTypes-2');
ListNameSpace.Add('qdt','urn:oasis:names:specification:ubl:schema:xsd:QualifiedDataTypes-2');
ListNameSpace.Add('ccts-cct','urn:un:unece:uncefact:data:specification:CoreComponentTypeSchemaModule:2');
ListNameSpace.Add('cct','urn:un:unece:uncefact:data:specification:CoreComponentTypeSchemaModule:2');
ListNameSpace.Add('sig','urn:oasis:names:specification:ubl:schema:xsd:CommonSignatureComponents-2');
ListNameSpace.Add('sac','urn:oasis:names:specification:ubl:schema:xsd:SignatureAggregateComponents-2');
ListNameSpace.Add('ds','http://www.w3.org/2000/09/xmldsig#');
ListNameSpace.Add('sbc','urn:oasis:names:specification:ubl:schema:xsd:SignatureBasicComponents-2');
ListNameSpace.Add('xsi','http://www.w3.org/2001/XMLSchema-instance');
end;
initialization
HookXMLNodeLibrary;
ListNameSpace := TDictionary<String,String>.Create;
AddNameSpace;
finalization
UnHookXMLNodeLibrary;
ListNameSpace.DisposeOf;
end.
示例输出:
Sally
1
A
N
以下是我尝试过的代码段。
Enter Student Name: Sally
How many subjects: 1
Grades for subject 1: A
Student Name: Sally
Grade: 4.00
Do you want to enter another student? N
答案 0 :(得分:2)
您的代码中存在两个问题:
scanf("%c",&grade[k1]);
scanf("%c",&ch1);
应替换为,
scanf(" %c",&grade[k1]); //notice the whitespace
scanf(" %c",&ch1);
这告诉scanf忽略空格!阅读它here
此外,您的计算GPA的代码应替换为:
gpa1=totalGrade/(float)totalSub1;
如果你不添加(浮动)字段gpa1会存储2.00,那么假设一个人的GPA为2.67!
答案 1 :(得分:0)
您的代码存在一些问题。这是你的固定代码。
#include <stdio.h>
int main()
{
char studentName[20];
char grade[10];
int k1;
int totalSub1,totalGrade;
float gpa1;
char ch1;
do
{
//Student Name
scanf("%s",studentName);
scanf("%d",&totalSub1);
//Get Grades
for(k1=0; k1<totalSub1; k1++)
{
//getchar(); //If you not interested to give extra space in scanf
scanf(" %c",&grade[k1]); //extra white space needed to discard ENTER from previous scanf
}
//Find the gade points
totalGrade=0; //Initialize totalGrade here not in the loop
for(k1=0; k1<totalSub1; k1++)
{
switch(grade[k1])
{
case 'A':
totalGrade+=4;
break;
case 'B':
totalGrade+=3;
break;
case 'C':
totalGrade+=2;
break;
case 'D':
totalGrade+=1;
break;
case 'F':
totalGrade+=0;
break;
}
}
//getchar();
scanf(" %c",&ch1);
printf("Enter Student Name: %s\n", studentName);
printf("How many subjects: %d\n",totalSub1);
for(k1=0; k1<totalSub1; k1++)
{
printf("Grades for subject %d: %c\n", k1+1, grade[k1]);
}
//Calculate GPA
gpa1=(float)totalGrade/totalSub1; //If you don't cast to float then gpa1 get result from integer division of totalGrade and totalSub1
//Print Student name with GPA
printf("Student Name: %s\n",studentName);
printf("Grade: %.2f\n",gpa1);
printf("Do you want to enter another student? %c\n", ch1);
}
while(ch1=='Y'||ch1=='y');
getchar();
return 0;
}